Moved challenge 4 to challenge 6 and introduced new sql injection challenge 5

This commit is contained in:
Nanne Baars 2017-05-03 14:33:58 +02:00
parent 4baceeb98b
commit ff89daf987
26 changed files with 695 additions and 470 deletions

View File

@ -45,7 +45,7 @@ public class Flag extends Endpoint {
@PostConstruct
public void initFlags() {
IntStream.range(1, 6).forEach(i -> FLAGS.put(i, UUID.randomUUID().toString()));
IntStream.range(1, 7).forEach(i -> FLAGS.put(i, UUID.randomUUID().toString()));
FLAGS.entrySet().stream().forEach(e -> log.debug("Flag {} {}", e.getKey(), e.getValue()));
}

View File

@ -12,6 +12,7 @@ public interface SolutionConstants {
String PASSWORD = "!!webgoat_admin_1234!!";
String SUPER_COUPON_CODE = "get_it_for_free";
String PASSWORD_TOM = "thisisasecretfortomonly";
String PASSWORD_LARRY = "larryknows";
String JWT_PASSWORD = "victory";
}

View File

@ -1,133 +1,17 @@
package org.owasp.webgoat.plugin.challenge4;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.plugin.Flag;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.owasp.webgoat.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.sql.*;
import static org.owasp.webgoat.plugin.SolutionConstants.PASSWORD_TOM;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
/**
* @author nbaars
* @since 4/8/17.
* @since 5/3/17.
*/
@AssignmentPath("/challenge/4")
@Slf4j
public class Assignment4 extends AssignmentEndpoint {
//Make it more random at runtime (good luck guessing)
private static final String USERS_TABLE_NAME = "challenge_users_" + RandomStringUtils.randomAlphabetic(16);
@Autowired
private WebSession webSession;
@PutMapping //assignment path is bounded to class so we use different http method :-)
@ResponseBody
public AttackResult registerNewUser(@RequestParam String username_reg, @RequestParam String email_reg, @RequestParam String password_reg) throws Exception {
AttackResult attackResult = checkArguments(username_reg, email_reg, password_reg);
if (attackResult == null) {
Connection connection = DatabaseUtilities.getConnection(webSession);
checkDatabase(connection);
String checkUserQuery = "select userid from " + USERS_TABLE_NAME + " where userid = '" + username_reg + "'";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(checkUserQuery);
if (resultSet.next()) {
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);
preparedStatement.setString(2, email_reg);
preparedStatement.setString(3, password_reg);
preparedStatement.execute();
attackResult = success().feedback("user.created").feedbackArgs(username_reg).build();
}
}
return attackResult;
}
private AttackResult checkArguments(String username_reg, String email_reg, String password_reg) {
if (StringUtils.isEmpty(username_reg) || StringUtils.isEmpty(email_reg) || StringUtils.isEmpty(password_reg)) {
return failed().feedback("input.invalid").build();
}
if (username_reg.length() > 250 || email_reg.length() > 30 || password_reg.length() > 30) {
return failed().feedback("input.invalid").build();
}
return null;
}
@RequestMapping(method = POST)
@ResponseBody
public AttackResult login(@RequestParam String username_login, @RequestParam String password_login) throws Exception {
Connection connection = DatabaseUtilities.getConnection(webSession);
checkDatabase(connection);
PreparedStatement statement = connection.prepareStatement("select password from " + USERS_TABLE_NAME + " where userid = ? and password = ?");
statement.setString(1, username_login);
statement.setString(2, password_login);
ResultSet resultSet = statement.executeQuery();
if (resultSet.next() && "tom".equals(username_login)) {
return success().feedback("challenge.solved").feedbackArgs(Flag.FLAGS.get(4)).build();
} else {
return failed().feedback("challenge.close").build();
}
}
private void checkDatabase(Connection connection) throws SQLException {
try {
Statement statement = connection.createStatement();
statement.execute("select 1 from " + USERS_TABLE_NAME);
} catch (SQLException e) {
createChallengeTable(connection);
}
}
private void createChallengeTable(Connection connection) {
Statement statement = null;
try {
statement = connection.createStatement();
String dropTable = "DROP TABLE " + USERS_TABLE_NAME;
statement.executeUpdate(dropTable);
} catch (SQLException e) {
log.info("Delete failed, this does not point to an error table might not have been present...");
}
log.debug("Challenge 4 - Creating tables for users {}", USERS_TABLE_NAME);
try {
String createTableStatement = "CREATE TABLE " + USERS_TABLE_NAME
+ " (" + "userid varchar(250),"
+ "email varchar(30),"
+ "password varchar(30)"
+ ")";
statement.executeUpdate(createTableStatement);
String insertData1 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('larry', 'larry@webgoat.org', 'larryknows')";
String insertData2 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('tom', 'tom@webgoat.org', '" + PASSWORD_TOM + "')";
String insertData3 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('alice', 'alice@webgoat.org', 'rt*(KJ()LP())$#**')";
String insertData4 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('eve', 'eve@webgoat.org', '**********')";
statement.executeUpdate(insertData1);
statement.executeUpdate(insertData2);
statement.executeUpdate(insertData3);
statement.executeUpdate(insertData4);
} catch (SQLException e) {
log.error("Unable create table", e);
}
}
//just empty, posting the flag will mark the challenge as done as well no need to specify an endpoint here
}

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.plugin.challenge5;
package org.owasp.webgoat.plugin.challenge4;
/**
* @author nbaars

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.plugin.challenge5;
package org.owasp.webgoat.plugin.challenge4;
import com.fasterxml.jackson.annotation.JsonView;
import lombok.Getter;

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.plugin.challenge5;
package org.owasp.webgoat.plugin.challenge4;
import com.google.common.collect.Maps;
import io.jsonwebtoken.*;
@ -89,7 +89,7 @@ public class VotesEndpoint {
if ("Guest".equals(user) || !validUsers.contains(user)) {
value.setSerializationView(Views.GuestView.class);
} else {
((Collection<Vote>) value.getValue()).forEach(v -> v.setFlag(FLAGS.get(5)));
((Collection<Vote>) value.getValue()).forEach(v -> v.setFlag(FLAGS.get(4)));
value.setSerializationView(isAdmin ? Views.AdminView.class : Views.UserView.class);
}
} catch (JwtException e) {

View File

@ -1,17 +0,0 @@
package org.owasp.webgoat.plugin.challenge5;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentPath;
/**
* @author nbaars
* @since 5/3/17.
*/
@AssignmentPath("/challenge/5")
@Slf4j
public class Assignment5 extends AssignmentEndpoint {
//just empty, posting the flag will mark the challenge as done as well no need to specify an endpoint here
}

View File

@ -0,0 +1,92 @@
package org.owasp.webgoat.plugin.challenge5.challenge6;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.plugin.Flag;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.owasp.webgoat.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.sql.*;
import static org.owasp.webgoat.plugin.SolutionConstants.PASSWORD_TOM;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
/**
* @author nbaars
* @since 4/8/17.
*/
@AssignmentPath("/challenge/5")
@Slf4j
public class Assignment5 extends AssignmentEndpoint {
//Make it more random at runtime (good luck guessing)
private static final String USERS_TABLE_NAME = "challenge_users_" + RandomStringUtils.randomAlphabetic(16);
@Autowired
private WebSession webSession;
@RequestMapping(method = POST)
@ResponseBody
public AttackResult login(@RequestParam String username_login, @RequestParam String password_login) throws Exception {
Connection connection = DatabaseUtilities.getConnection(webSession);
checkDatabase(connection);
PreparedStatement statement = connection.prepareStatement("select password from " + USERS_TABLE_NAME + " where userid = '" + username_login + "' and password = '" + password_login + "'");
ResultSet resultSet = statement.executeQuery();
if (resultSet.next()) {
return success().feedback("challenge.solved").feedbackArgs(Flag.FLAGS.get(5)).build();
} else {
return failed().feedback("challenge.close").build();
}
}
private void checkDatabase(Connection connection) throws SQLException {
try {
Statement statement = connection.createStatement();
statement.execute("select 1 from " + USERS_TABLE_NAME);
} catch (SQLException e) {
createChallengeTable(connection);
}
}
private void createChallengeTable(Connection connection) {
Statement statement = null;
try {
statement = connection.createStatement();
String dropTable = "DROP TABLE " + USERS_TABLE_NAME;
statement.executeUpdate(dropTable);
} catch (SQLException e) {
log.info("Delete failed, this does not point to an error table might not have been present...");
}
log.debug("Challenge 5 - Creating tables for users {}", USERS_TABLE_NAME);
try {
String createTableStatement = "CREATE TABLE " + USERS_TABLE_NAME
+ " (" + "userid varchar(250),"
+ "email varchar(30),"
+ "password varchar(30)"
+ ")";
statement.executeUpdate(createTableStatement);
String insertData1 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('larry', 'larry@webgoat.org', 'larryknows')";
String insertData2 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('tom', 'tom@webgoat.org', '" + PASSWORD_TOM + "')";
String insertData3 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('alice', 'alice@webgoat.org', 'rt*(KJ()LP())$#**')";
String insertData4 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('eve', 'eve@webgoat.org', '**********')";
statement.executeUpdate(insertData1);
statement.executeUpdate(insertData2);
statement.executeUpdate(insertData3);
statement.executeUpdate(insertData4);
} catch (SQLException e) {
log.error("Unable create table", e);
}
}
}

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.plugin.challenge5;
package org.owasp.webgoat.plugin.challenge5.challenge6;
import com.google.common.collect.Lists;
import org.owasp.webgoat.lessons.Category;

View File

@ -0,0 +1,133 @@
package org.owasp.webgoat.plugin.challenge6;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.plugin.Flag;
import org.owasp.webgoat.session.DatabaseUtilities;
import org.owasp.webgoat.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.sql.*;
import static org.owasp.webgoat.plugin.SolutionConstants.PASSWORD_TOM;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
/**
* @author nbaars
* @since 4/8/17.
*/
@AssignmentPath("/challenge/6")
@Slf4j
public class Assignment6 extends AssignmentEndpoint {
//Make it more random at runtime (good luck guessing)
private static final String USERS_TABLE_NAME = "challenge_users_" + RandomStringUtils.randomAlphabetic(16);
@Autowired
private WebSession webSession;
@PutMapping //assignment path is bounded to class so we use different http method :-)
@ResponseBody
public AttackResult registerNewUser(@RequestParam String username_reg, @RequestParam String email_reg, @RequestParam String password_reg) throws Exception {
AttackResult attackResult = checkArguments(username_reg, email_reg, password_reg);
if (attackResult == null) {
Connection connection = DatabaseUtilities.getConnection(webSession);
checkDatabase(connection);
String checkUserQuery = "select userid from " + USERS_TABLE_NAME + " where userid = '" + username_reg + "'";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(checkUserQuery);
if (resultSet.next()) {
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);
preparedStatement.setString(2, email_reg);
preparedStatement.setString(3, password_reg);
preparedStatement.execute();
attackResult = success().feedback("user.created").feedbackArgs(username_reg).build();
}
}
return attackResult;
}
private AttackResult checkArguments(String username_reg, String email_reg, String password_reg) {
if (StringUtils.isEmpty(username_reg) || StringUtils.isEmpty(email_reg) || StringUtils.isEmpty(password_reg)) {
return failed().feedback("input.invalid").build();
}
if (username_reg.length() > 250 || email_reg.length() > 30 || password_reg.length() > 30) {
return failed().feedback("input.invalid").build();
}
return null;
}
@RequestMapping(method = POST)
@ResponseBody
public AttackResult login(@RequestParam String username_login, @RequestParam String password_login) throws Exception {
Connection connection = DatabaseUtilities.getConnection(webSession);
checkDatabase(connection);
PreparedStatement statement = connection.prepareStatement("select password from " + USERS_TABLE_NAME + " where userid = ? and password = ?");
statement.setString(1, username_login);
statement.setString(2, password_login);
ResultSet resultSet = statement.executeQuery();
if (resultSet.next() && "tom".equals(username_login)) {
return success().feedback("challenge.solved").feedbackArgs(Flag.FLAGS.get(6)).build();
} else {
return failed().feedback("challenge.close").build();
}
}
private void checkDatabase(Connection connection) throws SQLException {
try {
Statement statement = connection.createStatement();
statement.execute("select 1 from " + USERS_TABLE_NAME);
} catch (SQLException e) {
createChallengeTable(connection);
}
}
private void createChallengeTable(Connection connection) {
Statement statement = null;
try {
statement = connection.createStatement();
String dropTable = "DROP TABLE " + USERS_TABLE_NAME;
statement.executeUpdate(dropTable);
} catch (SQLException e) {
log.info("Delete failed, this does not point to an error table might not have been present...");
}
log.debug("Challenge 6 - Creating tables for users {}", USERS_TABLE_NAME);
try {
String createTableStatement = "CREATE TABLE " + USERS_TABLE_NAME
+ " (" + "userid varchar(250),"
+ "email varchar(30),"
+ "password varchar(30)"
+ ")";
statement.executeUpdate(createTableStatement);
String insertData1 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('larry', 'larry@webgoat.org', 'larryknows')";
String insertData2 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('tom', 'tom@webgoat.org', '" + PASSWORD_TOM + "')";
String insertData3 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('alice', 'alice@webgoat.org', 'rt*(KJ()LP())$#**')";
String insertData4 = "INSERT INTO " + USERS_TABLE_NAME + " VALUES ('eve', 'eve@webgoat.org', '**********')";
statement.executeUpdate(insertData1);
statement.executeUpdate(insertData2);
statement.executeUpdate(insertData3);
statement.executeUpdate(insertData4);
} catch (SQLException e) {
log.error("Unable create table", e);
}
}
}

View File

@ -0,0 +1,39 @@
package org.owasp.webgoat.plugin.challenge6;
import com.google.common.collect.Lists;
import org.owasp.webgoat.lessons.Category;
import org.owasp.webgoat.lessons.NewLesson;
import java.util.List;
/**
* @author nbaars
* @since 3/21/17.
*/
public class Challenge6 extends NewLesson {
@Override
public Category getDefaultCategory() {
return Category.CHALLENGE;
}
@Override
public List<String> getHints() {
return Lists.newArrayList();
}
@Override
public Integer getDefaultRanking() {
return 10;
}
@Override
public String getTitle() {
return "challenge6.title";
}
@Override
public String getId() {
return "Challenge6";
}
}

View File

@ -11,8 +11,8 @@ li.active{border-bottom:3px solid silver;}
.btn-plus{cursor:pointer;font-size:7px;display:flex;align-items:center;padding:5px;padding-left:10px;padding-right:10px;border:1px solid gray;border-radius:2px;border-left:0px;}
div.section > div {width:100%;display:inline-flex;}
div.section > div > input {margin:0px;padding-left:5px;font-size:10px;padding-right:5px;max-width:18%;text-align:center;}
.attr,.attr2{cursor:pointer;margin-right:5px;height:20px;font-size:10px;padding:2px;border:1px solid gray;border-radius:2px;}
.attr.active,.attr2.active{ border:1px solid orange;}
.attr,.attr2{cursor:pointer;margin-right:5px;height:20px;font-size:11px;padding:2px;border:1px solid gray;border-radius:2px;}
.attr.active,.attr2.active{ border:2px solid orange;}
@media (max-width: 426px) {
.container {margin-top:0px !important;}

View File

@ -1,96 +1,12 @@
.panel-login {
border-color: #ccc;
-webkit-box-shadow: 0px 2px 3px 0px rgba(0,0,0,0.2);
-moz-box-shadow: 0px 2px 3px 0px rgba(0,0,0,0.2);
box-shadow: 0px 2px 3px 0px rgba(0,0,0,0.2);
a.list-group-item {
height:auto;
}
.panel-login>.panel-heading {
color: #00415d;
background-color: #fff;
border-color: #fff;
text-align:center;
a.list-group-item.active small {
color:#fff;
}
.panel-login>.panel-heading a{
text-decoration: none;
color: #666;
font-weight: bold;
font-size: 15px;
-webkit-transition: all 0.1s linear;
-moz-transition: all 0.1s linear;
transition: all 0.1s linear;
.stars {
margin:20px auto 1px;
}
.panel-login>.panel-heading a.active{
color: #029f5b;
font-size: 18px;
}
.panel-login>.panel-heading hr{
margin-top: 10px;
margin-bottom: 0px;
clear: both;
border: 0;
height: 1px;
background-image: -webkit-linear-gradient(left,rgba(0, 0, 0, 0),rgba(0, 0, 0, 0.15),rgba(0, 0, 0, 0));
background-image: -moz-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.15),rgba(0,0,0,0));
background-image: -ms-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.15),rgba(0,0,0,0));
background-image: -o-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.15),rgba(0,0,0,0));
}
.panel-login input[type="text"],.panel-login input[type="email"],.panel-login input[type="password"] {
height: 45px;
border: 1px solid #ddd;
font-size: 16px;
-webkit-transition: all 0.1s linear;
-moz-transition: all 0.1s linear;
transition: all 0.1s linear;
}
.panel-login input:hover,
.panel-login input:focus {
outline:none;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
border-color: #ccc;
}
.btn-login {
background-color: #59B2E0;
outline: none;
color: #fff;
font-size: 14px;
height: auto;
font-weight: normal;
padding: 14px 0;
text-transform: uppercase;
border-color: #59B2E6;
}
.btn-login:hover,
.btn-login:focus {
color: #fff;
background-color: #53A3CD;
border-color: #53A3CD;
}
.forgot-password {
text-decoration: underline;
color: #888;
}
.forgot-password:hover,
.forgot-password:focus {
text-decoration: underline;
color: #666;
}
.btn-register {
background-color: #1CB94E;
outline: none;
color: #fff;
font-size: 14px;
height: auto;
font-weight: normal;
padding: 14px 0;
text-transform: uppercase;
border-color: #1CB94A;
}
.btn-register:hover,
.btn-register:focus {
color: #fff;
background-color: #1CA347;
border-color: #1CA347;
.img-responsive {
min-width: 100%;
}

View File

@ -1,12 +0,0 @@
a.list-group-item {
height:auto;
}
a.list-group-item.active small {
color:#fff;
}
.stars {
margin:20px auto 1px;
}
.img-responsive {
min-width: 100%;
}

View File

@ -0,0 +1,96 @@
.panel-login {
border-color: #ccc;
-webkit-box-shadow: 0px 2px 3px 0px rgba(0,0,0,0.2);
-moz-box-shadow: 0px 2px 3px 0px rgba(0,0,0,0.2);
box-shadow: 0px 2px 3px 0px rgba(0,0,0,0.2);
}
.panel-login>.panel-heading {
color: #00415d;
background-color: #fff;
border-color: #fff;
text-align:center;
}
.panel-login>.panel-heading a{
text-decoration: none;
color: #666;
font-weight: bold;
font-size: 15px;
-webkit-transition: all 0.1s linear;
-moz-transition: all 0.1s linear;
transition: all 0.1s linear;
}
.panel-login>.panel-heading a.active{
color: #029f5b;
font-size: 18px;
}
.panel-login>.panel-heading hr{
margin-top: 10px;
margin-bottom: 0px;
clear: both;
border: 0;
height: 1px;
background-image: -webkit-linear-gradient(left,rgba(0, 0, 0, 0),rgba(0, 0, 0, 0.15),rgba(0, 0, 0, 0));
background-image: -moz-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.15),rgba(0,0,0,0));
background-image: -ms-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.15),rgba(0,0,0,0));
background-image: -o-linear-gradient(left,rgba(0,0,0,0),rgba(0,0,0,0.15),rgba(0,0,0,0));
}
.panel-login input[type="text"],.panel-login input[type="email"],.panel-login input[type="password"] {
height: 45px;
border: 1px solid #ddd;
font-size: 16px;
-webkit-transition: all 0.1s linear;
-moz-transition: all 0.1s linear;
transition: all 0.1s linear;
}
.panel-login input:hover,
.panel-login input:focus {
outline:none;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
border-color: #ccc;
}
.btn-login {
background-color: #59B2E0;
outline: none;
color: #fff;
font-size: 14px;
height: auto;
font-weight: normal;
padding: 14px 0;
text-transform: uppercase;
border-color: #59B2E6;
}
.btn-login:hover,
.btn-login:focus {
color: #fff;
background-color: #53A3CD;
border-color: #53A3CD;
}
.forgot-password {
text-decoration: underline;
color: #888;
}
.forgot-password:hover,
.forgot-password:focus {
text-decoration: underline;
color: #666;
}
.btn-register {
background-color: #1CB94E;
outline: none;
color: #fff;
font-size: 14px;
height: auto;
font-weight: normal;
padding: 14px 0;
text-transform: uppercase;
border-color: #1CB94A;
}
.btn-register:hover,
.btn-register:focus {
color: #fff;
background-color: #1CA347;
border-color: #1CA347;
}

View File

@ -6,100 +6,50 @@
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:Challenge_4.adoc"></div>
<link rel="stylesheet" type="text/css" th:href="@{/lesson_css/challenge4.css}"/>
<script th:src="@{/lesson_js/bootstrap.min.js}" language="JavaScript"></script>
<script th:src="@{/lesson_js/challenge4.js}" language="JavaScript"></script>
<div class="attack-container">
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<div class="container-fluid">
<div class="row">
<div class="col-md-6">
<div class="panel panel-login">
<div class="panel-heading">
<div class="row">
<div class="col-xs-6">
<a href="#" class="active" id="login-form-link">Login</a>
</div>
<div class="col-xs-6">
<a href="#" id="register-form-link">Register</a>
</div>
</div>
<hr/>
<div class="well">
<div class="pull-right">
<div class="dropdown">
<button type="button" data-toggle="dropdown" class="btn btn-default dropdown-toggle">
<i class="fa fa-user"></i> <span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-left">
<li role="presentation"><a role="menuitem" tabindex="-1"
onclick="javascript:login('Guest')"
th:text="Guest">current</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1"
onclick="javascript:login('Tom')"
th:text="Tom">current</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1"
onclick="javascript:login('Jerry')"
th:text="Jerry">current</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1"
onclick="javascript:login('Sylvester')"
th:text="Sylvester">current</a></li>
</ul>
</div>
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
<form id="login-form" class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/challenge/4"
enctype="application/json;charset=UTF-8" role="form">
<div class="form-group">
<input type="text" name="username_login" id="username4" tabindex="1"
class="form-control" placeholder="Username" value=""/>
</div>
<div class="form-group">
<input type="password" name="password_login" id="password4" tabindex="2"
class="form-control" placeholder="Password"/>
</div>
<div class="form-group text-center">
<input type="checkbox" tabindex="3" class="" name="remember" id="remember"/>
<label for="remember"> Remember me</label>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<input type="submit" name="login-submit" id="login-submit"
tabindex="4" class="form-control btn-primary"
value="Log In"/>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-lg-12">
<div class="text-center">
<a href="#" tabindex="5" class="forgot-password">Forgot
Password?</a>
</div>
</div>
</div>
</div>
</form>
<form id="register-form" class="attack-form" accept-charset="UNKNOWN"
method="PUT" name="form"
action="/WebGoat/challenge/4"
enctype="application/json;charset=UTF-8" style="display: none;" role="form">
<div class="form-group">
<input type="text" name="username_reg" id="username" tabindex="1"
class="form-control" placeholder="Username" value=""/>
</div>
<div class="form-group">
<input type="email" name="email_reg" id="email" tabindex="1"
class="form-control" placeholder="Email Address" value=""/>
</div>
<div class="form-group">
<input type="password" name="password_reg" id="password" tabindex="2"
class="form-control" placeholder="Password"/>
</div>
<div class="form-group">
<input type="password" name="confirm_password_reg" id="confirm-password"
tabindex="2" class="form-control" placeholder="Confirm Password"/>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<input type="submit" name="register-submit" id="register-submit"
tabindex="4" class="form-control btn btn-primary"
value="Register Now"/>
</div>
</div>
</div>
</form>
</div>
</div>
<div>
<p class="text-right">Welcome back, <b><span id="name"></span></b></p>
</div>
</div>
<div>
<h3>Vote for your favorite</h3>
</div>
<div id ="votesList" class="list-group">
</div>
</div>
</div>
</div>
<br/>
<form class="attack-form" method="POST" name="form" action="/WebGoat/challenge/flag">
<div class="form-group">

View File

@ -5,51 +5,67 @@
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:Challenge_5.adoc"></div>
<link rel="stylesheet" type="text/css" th:href="@{/lesson_css/challenge5.css}"/>
<script th:src="@{/lesson_js/bootstrap.min.js}" language="JavaScript"></script>
<script th:src="@{/lesson_js/challenge5.js}" language="JavaScript"></script>
<link rel="stylesheet" type="text/css" th:href="@{/lesson_css/challenge6.css}"/>
<div class="attack-container">
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<div class="container-fluid">
<div class="row">
<div class="well">
<div class="pull-right">
<div class="dropdown">
<button type="button" data-toggle="dropdown" class="btn btn-default dropdown-toggle">
<i class="fa fa-user"></i> <span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-left">
<li role="presentation"><a role="menuitem" tabindex="-1"
onclick="javascript:login('Guest')"
th:text="Guest">current</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1"
onclick="javascript:login('Tom')"
th:text="Tom">current</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1"
onclick="javascript:login('Jerry')"
th:text="Jerry">current</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1"
onclick="javascript:login('Sylvester')"
th:text="Sylvester">current</a></li>
</ul>
<div class="col-md-6">
<div class="panel panel-login">
<div class="panel-heading">
<div class="row">
<div class="col-xs-6">
<a href="#" class="active" id="login-form-link">Login</a>
</div>
</div>
<hr/>
</div>
<div>
<p class="text-right">Welcome back, <b><span id="name"></span></b></p>
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
<form id="login-form" class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/challenge/5"
enctype="application/json;charset=UTF-8" role="form">
<div class="form-group">
<input type="text" name="username_login" id="username4" tabindex="1"
class="form-control" placeholder="Username" value=""/>
</div>
<div class="form-group">
<input type="password" name="password_login" id="password4" tabindex="2"
class="form-control" placeholder="Password"/>
</div>
<div class="form-group text-center">
<input type="checkbox" tabindex="3" class="" name="remember" id="remember"/>
<label for="remember"> Remember me</label>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<input type="submit" name="login-submit" id="login-submit"
tabindex="4" class="form-control btn-primary"
value="Log In"/>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-lg-12">
<div class="text-center">
<a href="#" tabindex="5" class="forgot-password">Forgot
Password?</a>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<div>
<h3>Vote for your favorite</h3>
</div>
<div id ="votesList" class="list-group">
</div>
</div>
</div>
</div>
<br/>
<form class="attack-form" method="POST" name="form" action="/WebGoat/challenge/flag">
<div class="form-group">

View File

@ -0,0 +1,125 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div class="lesson-page-wrapper">
<div class="adoc-content" th:replace="doc:Challenge_6.adoc"></div>
<link rel="stylesheet" type="text/css" th:href="@{/lesson_css/challenge6.css}"/>
<script th:src="@{/lesson_js/challenge6.js}" language="JavaScript"></script>
<div class="attack-container">
<div class="assignment-success"><i class="fa fa-2 fa-check hidden" aria-hidden="true"></i></div>
<div class="container-fluid">
<div class="row">
<div class="col-md-6">
<div class="panel panel-login">
<div class="panel-heading">
<div class="row">
<div class="col-xs-6">
<a href="#" class="active" id="login-form-link">Login</a>
</div>
<div class="col-xs-6">
<a href="#" id="register-form-link">Register</a>
</div>
</div>
<hr/>
</div>
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
<form id="login-form" class="attack-form" accept-charset="UNKNOWN"
method="POST" name="form"
action="/WebGoat/challenge/6"
enctype="application/json;charset=UTF-8" role="form">
<div class="form-group">
<input type="text" name="username_login" id="username4" tabindex="1"
class="form-control" placeholder="Username" value=""/>
</div>
<div class="form-group">
<input type="password" name="password_login" id="password4" tabindex="2"
class="form-control" placeholder="Password"/>
</div>
<div class="form-group text-center">
<input type="checkbox" tabindex="3" class="" name="remember" id="remember"/>
<label for="remember"> Remember me</label>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<input type="submit" name="login-submit" id="login-submit"
tabindex="4" class="form-control btn-primary"
value="Log In"/>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-lg-12">
<div class="text-center">
<a href="#" tabindex="5" class="forgot-password">Forgot
Password?</a>
</div>
</div>
</div>
</div>
</form>
<form id="register-form" class="attack-form" accept-charset="UNKNOWN"
method="PUT" name="form"
action="/WebGoat/challenge/6"
enctype="application/json;charset=UTF-8" style="display: none;" role="form">
<div class="form-group">
<input type="text" name="username_reg" id="username" tabindex="1"
class="form-control" placeholder="Username" value=""/>
</div>
<div class="form-group">
<input type="email" name="email_reg" id="email" tabindex="1"
class="form-control" placeholder="Email Address" value=""/>
</div>
<div class="form-group">
<input type="password" name="password_reg" id="password" tabindex="2"
class="form-control" placeholder="Password"/>
</div>
<div class="form-group">
<input type="password" name="confirm_password_reg" id="confirm-password"
tabindex="2" class="form-control" placeholder="Confirm Password"/>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<input type="submit" name="register-submit" id="register-submit"
tabindex="4" class="form-control btn btn-primary"
value="Register Now"/>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<br/>
<form class="attack-form" method="POST" name="form" action="/WebGoat/challenge/flag">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-flag-checkered" aria-hidden="true"
style="font-size:20px"></i></div>
<input type="text" class="form-control" id="flag" name="flag"
placeholder="a7179f89-906b-4fec-9d99-f15b796e7208"/>
</div>
<div class="input-group" style="margin-top: 10px">
<button type="submit" class="btn btn-primary">Submit flag</button>
</div>
</div>
</form>
<br/>
<div class="attack-feedback"></div>
<div class="attack-output"></div>
</div>
</div>
</html>

View File

@ -2,8 +2,9 @@ challenge0.title=WebGoat Challenge
challenge1.title=Admin lost password
challenge2.title=Get it for free
challenge3.title=Photo comments
challenge4.title=Creating a new account
challenge5.title=Voting
challenge4.title=Voting
challenge5.title=Without password
challenge6.title=Creating a new account
challenge.solved=Congratulations, you solved the challenge. Here is your flag: {0}
challenge.close=This is not the correct password for tom, please try again.

View File

@ -1,18 +1,84 @@
$(function() {
$(document).ready(function () {
login('Guest');
})
$('#login-form-link').click(function(e) {
$("#login-form").delay(100).fadeIn(100);
$("#register-form").fadeOut(100);
$('#register-form-link').removeClass('active');
$(this).addClass('active');
e.preventDefault();
});
$('#register-form-link').click(function(e) {
$("#register-form").delay(100).fadeIn(100);
$("#login-form").fadeOut(100);
$('#login-form-link').removeClass('active');
$(this).addClass('active');
e.preventDefault();
function login(user) {
$("#name").text(user);
$.ajax({
url: "votings/login?user=" + user,
complete: function (result, status) {
getVotings();
}
});
}
var html = '<a href="#" class="list-group-item ACTIVE">' +
'<div class="media col-md-3">' +
'<figure> ' +
'<img class="media-object img-rounded" src="images/IMAGE_SMALL" alt="placehold.it/350x250"/>' +
'</figure>' +
'</div> ' +
'<div class="col-md-6">' +
'<h4 class="list-group-item-heading">TITLE</h4>' +
'<p class="list-group-item-text">INFORMATION</p>' +
'</div>' +
'<div class="col-md-3 text-center">' +
'<h2 HIDDEN_VIEW_VOTES>NO_VOTES' +
'<small HIDDEN_VIEW_VOTES> votes</small>' +
'</h2>' +
'<button type="button" id="TITLE" class="btn BUTTON btn-lg btn-block" onclick="vote(this.id)">Vote Now!</button>' +
'<div style="visibility:HIDDEN_VIEW_RATING;" class="stars"> ' +
'<span class="glyphicon glyphicon-star"></span>' +
'<span class="glyphicon glyphicon-star"></span>' +
'<span class="glyphicon glyphicon-star"></span>' +
'<span class="glyphicon glyphicon-star-empty"></span>' +
'</div>' +
'<p HIDDEN_VIEW_RATING>Average AVERAGE<small> /</small>4</p>' +
'</div>' +
'<div class="clearfix"></div>' +
'</a>';
function getVotings() {
$("#votesList").empty();
$.get("votings/", function (result, status) {
for (var i = 0; i < result.length; i++) {
var voteTemplate = html.replace('IMAGE_SMALL', result[i].imageSmall);
if (i === 0) {
voteTemplate = voteTemplate.replace('ACTIVE', 'active');
voteTemplate = voteTemplate.replace('BUTTON', 'btn-default');
} else {
voteTemplate = voteTemplate.replace('ACTIVE', '');
voteTemplate = voteTemplate.replace('BUTTON', 'btn-primary');
}
voteTemplate = voteTemplate.replace(/TITLE/g, result[i].title);
voteTemplate = voteTemplate.replace('INFORMATION', result[i].information || '');
voteTemplate = voteTemplate.replace('NO_VOTES', result[i].numberOfVotes || '');
voteTemplate = voteTemplate.replace('AVERAGE', result[i].average || '');
var hidden = (result[i].numberOfVotes === undefined ? 'hidden' : '');
voteTemplate = voteTemplate.replace(/HIDDEN_VIEW_VOTES/g, hidden);
hidden = (result[i].average === undefined ? 'hidden' : '');
voteTemplate = voteTemplate.replace(/HIDDEN_VIEW_RATING/g, hidden);
$("#votesList").append(voteTemplate);
}
})
}
function vote(title) {
var user = $("#name").text();
if (user === 'Guest') {
alert("As a guest you are not allowed to vote, please login first.")
} else {
$.ajax({
type: 'POST',
url: 'votings/' + title
}).then(
function () {
getVotings();
}
)
}
}
});

View File

@ -1,84 +0,0 @@
$(document).ready(function () {
login('Guest');
})
function login(user) {
$("#name").text(user);
$.ajax({
url: "votings/login?user=" + user,
complete: function (result, status) {
getVotings();
}
});
}
var html = '<a href="#" class="list-group-item ACTIVE">' +
'<div class="media col-md-3">' +
'<figure> ' +
'<img class="media-object img-rounded" src="images/IMAGE_SMALL" alt="placehold.it/350x250"/>' +
'</figure>' +
'</div> ' +
'<div class="col-md-6">' +
'<h4 class="list-group-item-heading">TITLE</h4>' +
'<p class="list-group-item-text">INFORMATION</p>' +
'</div>' +
'<div class="col-md-3 text-center">' +
'<h2 HIDDEN_VIEW_VOTES>NO_VOTES' +
'<small HIDDEN_VIEW_VOTES> votes</small>' +
'</h2>' +
'<button type="button" id="TITLE" class="btn BUTTON btn-lg btn-block" onclick="vote(this.id)">Vote Now!</button>' +
'<div style="visibility:HIDDEN_VIEW_RATING;" class="stars"> ' +
'<span class="glyphicon glyphicon-star"></span>' +
'<span class="glyphicon glyphicon-star"></span>' +
'<span class="glyphicon glyphicon-star"></span>' +
'<span class="glyphicon glyphicon-star-empty"></span>' +
'</div>' +
'<p HIDDEN_VIEW_RATING>Average AVERAGE<small> /</small>4</p>' +
'</div>' +
'<div class="clearfix"></div>' +
'</a>';
function getVotings() {
$("#votesList").empty();
$.get("votings/", function (result, status) {
for (var i = 0; i < result.length; i++) {
var voteTemplate = html.replace('IMAGE_SMALL', result[i].imageSmall);
if (i === 0) {
voteTemplate = voteTemplate.replace('ACTIVE', 'active');
voteTemplate = voteTemplate.replace('BUTTON', 'btn-default');
} else {
voteTemplate = voteTemplate.replace('ACTIVE', '');
voteTemplate = voteTemplate.replace('BUTTON', 'btn-primary');
}
voteTemplate = voteTemplate.replace(/TITLE/g, result[i].title);
voteTemplate = voteTemplate.replace('INFORMATION', result[i].information || '');
voteTemplate = voteTemplate.replace('NO_VOTES', result[i].numberOfVotes || '');
voteTemplate = voteTemplate.replace('AVERAGE', result[i].average || '');
var hidden = (result[i].numberOfVotes === undefined ? 'hidden' : '');
voteTemplate = voteTemplate.replace(/HIDDEN_VIEW_VOTES/g, hidden);
hidden = (result[i].average === undefined ? 'hidden' : '');
voteTemplate = voteTemplate.replace(/HIDDEN_VIEW_RATING/g, hidden);
$("#votesList").append(voteTemplate);
}
})
}
function vote(title) {
var user = $("#name").text();
if (user === 'Guest') {
alert("As a guest you are not allowed to vote, please login first.")
} else {
$.ajax({
type: 'POST',
url: 'votings/' + title
}).then(
function () {
getVotings();
}
)
}
}

View File

@ -0,0 +1,18 @@
$(function() {
$('#login-form-link').click(function(e) {
$("#login-form").delay(100).fadeIn(100);
$("#register-form").fadeOut(100);
$('#register-form-link').removeClass('active');
$(this).addClass('active');
e.preventDefault();
});
$('#register-form-link').click(function(e) {
$("#register-form").delay(100).fadeIn(100);
$("#login-form").fadeOut(100);
$('#login-form-link').removeClass('active');
$(this).addClass('active');
e.preventDefault();
});
});

View File

@ -1 +1 @@
Can you login as Tom?
Try to change to a different user, maybe you can find the flag?

View File

@ -1 +1 @@
Try to change to a different user, maybe you can find the flag?
Can you login as Larry?

View File

@ -0,0 +1 @@
Can you login as Tom?

View File

@ -1,4 +1,4 @@
package org.owasp.webgoat.plugin.challenge5;
package org.owasp.webgoat.plugin.challenge4;
import org.hamcrest.CoreMatchers;
import org.junit.Before;