Refactoring (#1201)

* Some initial refactoring

* Make it one application

* Got it working

* Fix problem on Windows

* Move WebWolf

* Move first lesson

* Moved all lessons

* Fix pom.xml

* Fix tests

* Add option to initialize a lesson

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

* Clean up pom.xml files

* Remove fetching labels based on language.

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

* Fix SonarLint issues

* And move it all to the main project

* Fix for documentation paths

* Fix pom warnings

* Remove PMD as it does not work

* Update release notes about refactoring

Update release notes about refactoring

Update release notes about refactoring

* Fix lesson template

* Update release notes

* Keep it in the same repo in Dockerhub

* Update documentation to show how the connection is obtained.

Resolves: #1180

* Rename all integration tests

* Remove command from Dockerfile

* Simplify GitHub actions

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

* Remove duplicate entry from release notes

* Add explicit registry for base image

* Lesson scanner not working when fat jar

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

* added info in README and fixed release docker

* changed base image and added ignore file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,87 @@
footer {
margin-top: 200px;
}
.thead-inverse th {
color: #fff;
background-color: #373a3c;
}
.left15 {
margin-left: 15px;
}
.top5 {
margin-top: 5px;
}
.top7 {
margin-top: 7px;
}
.top10 {
margin-top: 10px;
}
.top15 {
margin-top: 15px;
}
.top17 {
margin-top: 17px;
}
.top30 {
margin-top: 30px;
}
.bottom10 {
margin-bottom: 10px;
}
#accordion .panel-heading {
padding: 0;
}
#accordion .panel-title > a {
display: block;
padding: 0.4em 0.6em;
outline: none;
font-weight: bold;
text-decoration: none;
}
#accordion .panel-title > a.accordion-toggle::before, #accordion a[data-toggle="collapse"]::before {
content: "\e113";
float: left;
font-family: 'Glyphicons Halflings';
margin-right: 1em;
}
#accordion .panel-title > a.accordion-toggle.collapsed::before, #accordion a.collapsed[data-toggle="collapse"]::before {
content: "\e114";
}
textarea {
height: 250px;
overflow: auto;
width: 100%;
padding: 1%;
border: none;
}
/*Mailbox*/
.nav-tabs .glyphicon:not(.no-margin) { margin-right:10px; }
.tab-pane .list-group-item:first-child {border-top-right-radius: 0px;border-top-left-radius: 0px;}
.tab-pane .list-group-item:last-child {border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;}
.tab-pane .list-group .checkbox { display: inline-block;margin: 0px; }
.tab-pane .list-group input[type="checkbox"]{ margin-top: 2px; }
.tab-pane .list-group .glyphicon { margin-right:5px; }
.tab-pane .list-group .glyphicon:hover { color:#FFBC00; }
a.list-group-item.read { color: #222;background-color: #F3F3F3; }
hr { margin-top: 5px;margin-bottom: 10px; }
.nav-pills>li>a {padding: 5px 10px;}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -0,0 +1,11 @@
$(document).ready(function() {
window.setTimeout(function () {
$(".fileUploadAlert").fadeTo(500, 0).slideUp(500, function () {
$(this).hide();
});
}, 4000);
});
$(document).on('click','.fa-files-o',function(){
document.execCommand('copy');
});

View File

@ -0,0 +1,47 @@
(function ($) {
$.fn.getFormData = function () {
var data = {};
var dataArray = $(this).serializeArray();
for (var i = 0; i < dataArray.length; i++) {
data[dataArray[i].name] = dataArray[i].value;
}
return data;
}
})(jQuery);
$(document).ready(() => {
$('#payload').on('input', call(true));
$('#header').on('input', call(true));
$('#secretKey').on('input', call(true));
$('#token').on('input', call(false));
});
function call(encode) {
return () => {
var url = encode ? '/WebWolf/jwt/encode' : '/WebWolf/jwt/decode';
var formData = encode ? $('#encodeForm').getFormData() : $('#decodeForm').getFormData();
formData["secretKey"] = $('#secretKey').val();
$.ajax({
type: 'POST',
url: url,
data: formData,
success: function (data) {
update(data)
},
contentType: "application/x-www-form-urlencoded",
dataType: 'json'
});
}
}
function update(token) {
$('#token').val(token.encoded);
$('#payload').val(token.payload);
$('#header').val(token.header);
$('#token').css('background-color', token.validToken ? '#FFFFFF' : 'lightcoral');
$('#header').css('background-color', token.validHeader ? '#FFFFFF' : 'lightcoral');
$('#payload').css('background-color', token.validPayload ? '#FFFFFF' : 'lightcoral');
$('#signatureValid').html(token.signatureValid ? "Signature valid" : "Signature invalid");
}

View File

@ -0,0 +1,10 @@
$(document).ready(function () {
$('.showMail').click(function (e) {
e.preventDefault();
$(this).parent().find('.contents').toggle()
});
});
function refreshEmails() {
location.reload();
}

View File

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>WebWolf</title>
<div th:replace="fragments/header :: header-css"/>
</head>
<body>
<div th:replace="fragments/header :: header"/>
<div class="container">
<h1>WebWolf</h1>
<p>This is the general error page of WebWolf. It applies for all 404, 500 etc messages.</p>
<p>Sometimes you will end up on this page on purpose because of a fake call to WebGoat which is redirected to WebWolf.
In that situation, you are probably interested in seeing the detail of the request. Login to WebWolf and check the incoming requests.</p>
<br/>
<table>
<tr>
<td>Date: </td>
<td th:text="${timestamp}"/>
</tr>
<tr>
<td>Path: </td>
<td th:text="${path}"/>
</tr>
<tr>
<td>Status: </td>
<td th:text="${status}"/>
</tr>
</table>
</div>
<!-- /.container -->
<div th:replace="fragments/footer :: footer"/>
</body>
</html>

View File

@ -0,0 +1,72 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:replace="fragments/header :: header-css"/>
</head>
<body>
<div th:replace="fragments/header :: header"/>
<script type="text/javascript" th:src="@{/js/fileUpload.js}"></script>
<div class="container">
<div class="alert alert-info fade in">
<a href="#" class="close" data-dismiss="alert">&times;</a>
<p>
Upload a file which you need to host as an attacker.
</p>
<p>
Each file will be available under the following url:
<span th:text="${webwolf_url}">http://localhost:9090/WebWolf/</span>/files/{username}/{filename}.
</p>
<p>
You can copy and paste the location from the table below.
</p>
</div>
<div class="panel panel-default">
<div class="panel-heading"><strong>Upload a file</strong>
<small></small>
</div>
<div class="panel-body">
<!-- Standard Form -->
<form th:action="@{/fileupload}" method="post" enctype="multipart/form-data">
<div class="form-inline">
<div class="form-group">
<input type="file" name="file"/>
</div>
<button type="submit" class="btn btn-md btn-primary">Upload files</button>
</div>
</form>
<div class="fileUploadAlert alert-success top10" role="alert">
<span th:text="${uploadSuccess}"></span>
</div>
</div>
</div>
<table class="table">
<thead class="thead-inverse">
<tr>
<th>Filename</th>
<th>Size</th>
<th>Link</th>
</tr>
</thead>
<tbody>
<tr th:each="f : ${files}">
<td th:text="${f.name}">filename</td>
<td th:text="${f.size}">size</td>
<td><a th:id="fileLink" th:href="@{'/' + ${f.link}}">link</a>
<span class="fa fa-files-o" title="Click to copy to clipboard"></span>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

View File

@ -0,0 +1,16 @@
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
</head>
<body>
<div th:fragment="footer">
<div class="container">
<footer>
© 2021 WebGoat - Use WebWolf at your own risk
</footer>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,53 @@
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
<title>WebWolf</title>
<div th:fragment="header-css">
<link rel="icon" th:href="@{/css/img/webwolf.ico}"/>
<link rel="stylesheet" type="text/css" th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap.min.css}"/>
<link rel="stylesheet" th:href="@{/css/webwolf.css}"/>
<script th:src="@{/webjars/jquery/3.5.1/jquery.min.js}"></script>
<script th:src="@{/webjars/bootstrap/3.3.7/js/bootstrap.min.js}"></script>
</div>
</head>
<body>
<div th:fragment="header">
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" th:href="@{/home}">WebWolf</a>
</div>
<ul class="nav navbar-nav">
<li class="active"><a th:href="@{/home}">Home</a></li>
</ul>
<ul class="nav navbar-nav">
<li><a th:href="@{/files}">Files</a></li>
</ul>
<ul class="nav navbar-nav">
<li><a th:href="@{/mail}">Mailbox</a></li>
</ul>
<ul class="nav navbar-nav">
<li><a th:href="@{/requests}">Incoming requests</a></li>
</ul>
<ul class="nav navbar-nav">
<li><a th:href="@{/jwt}">JWT</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">
<span sec:authorize="isAuthenticated()">
<span class="glyphicon glyphicon-user"></span>
<span th:text="${#authentication.name}"></span></span></a>
</li>
<li><a th:href="@{/logout}">
<span sec:authorize="isAuthenticated()">
Sign out</span></a>
</li>
</ul>
</div>
</nav>
</div>
</body>
</html>

View File

@ -0,0 +1,37 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:replace="fragments/header :: header-css"/>
</head>
<body>
<div th:replace="fragments/header :: header"/>
<div class="container">
<div class="media">
<span class="media-left">
<img th:src="@{/images/wolf.png}" class="img-fluid"></img>
</span>
<div class="media-body">
<h1 class="media-heading">WebWolf</h1>
<br/>
<p>
Some challenges requires to have a local web server running. WebWolf is for you the attacker it
helps you while solving some of the assignments and challenges within
WebGoat. An assignment might for example require you to serve a file or connect back to your own
environment or to receive an e-mail.
In order to not let you run WebGoat open and connected to the internet we provided these tools in this
application, called WebWolf.
</p>
</div>
</div>
</div>
<!-- /.container -->
<div th:replace="fragments/footer :: footer"/>
</body>
</html>

View File

@ -0,0 +1,70 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:replace="fragments/header :: header-css"/>
</head>
<body>
<div th:replace="fragments/header :: header"/>
<script type="text/javascript" th:src="@{/js/jwt.js}"></script>
<div class="container">
<div class="alert alert-info fade in">
<a href="#" class="close" data-dismiss="alert">&times;</a>
<p>
Decode or encode a JWT some of the exercises need to encode or decode a new token
</p>
</div>
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="form-group">
<label for="token">Encoded</label>
<form id="decodeForm">
<textarea class="form-control" style="font-size: 14pt; font-family:monospace;" id="token" name="token"
rows="4"
placeholder="Paste token here" spellcheck="false"></textarea>
</form>
</div>
<form id="encodeForm">
<div class="form-group">
<label>Decoded</label>
<div class="row">
<div class="col-xs-6 col-md-5">Header</div>
<div class="col-xs-6 col-md-7">Payload</div>
</div>
<div class="row">
<div class="col-xs-6 col-md-5">
<textarea class="form-control" style="font-size: 14pt; font-family:monospace;" id="header"
name="header"
rows="12"></textarea>
</div>
<div class="col-xs-6 col-md-7">
<textarea class="form-control" style="font-size: 14pt; font-family:monospace;" id="payload"
name="payload"
rows="12"></textarea>
</div>
</div>
</div>
</form>
<br/>
<div class="input-group">
<span class="input-group-addon">Secret key</span>
<input type="text" placeholder="Enter your secret key" class="form-control" id="secretKey">
</div>
<div class="input-group">
<h4 id="signatureValid">Invalid signature</h4>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,150 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>WebWolf</title>
<div th:replace="fragments/header :: header-css"/>
</head>
<body>
<div th:replace="fragments/header :: header"/>
<script type="text/javascript" th:src="@{/js/mail.js}"></script>
<div class="container">
<div class="alert alert-info fade in">
<a href="#" class="close" data-dismiss="alert">&times;</a>
<p>
The mailbox of you as an attacker, all the mail send to {user}@{random} will be send to this mailbox.
</p>
<p>
Only the user part is important the domain can be anything
</p>
</div>
<div class="panel panel-default">
<div class="panel-body">
<div class="row">
<div class="col-sm-3 col-md-2">
<div class="btn-group">
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
Mail <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Mail</a></li>
<li><a href="#">Contacts</a></li>
<li><a href="#">Tasks</a></li>
</ul>
</div>
</div>
<div class="col-sm-9 col-md-10">
<button type="button" class="btn btn-default" data-toggle="tooltip" title="Refresh" onclick="refreshEmails()">
   <span class="glyphicon glyphicon-refresh"></span>   
</button>
<!-- Single button -->
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
More <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Mark all as read</a></li>
<li class="divider"></li>
<li class="text-center">
<small class="text-muted">Select messages to see more actions</small>
</li>
</ul>
</div>
<div class="pull-right">
<span class="text-muted"><b>1</b><b><span th:text="${total}"> 50</span> </b> of <b><span th:utext="${total}"></span></b></span>
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-default">
<span class="glyphicon glyphicon-chevron-left"></span>
</button>
<button type="button" class="btn btn-default">
<span class="glyphicon glyphicon-chevron-right"></span>
</button>
</div>
</div>
</div>
</div>
<hr/>
<div class="row">
<div class="col-sm-3 col-md-2">
<a href="#" class="btn btn-danger btn-sm btn-block" role="button">COMPOSE</a>
<hr/>
<ul class="nav nav-pills nav-stacked">
<li class="active"><a href="#"><span class="badge pull-right" th:utext="${total}">42</span>
Inbox </a>
</li>
</ul>
</div>
<div class="col-sm-9 col-md-10">
<!-- Nav tabs -->
<ul class="nav nav-tabs">
<li class="active"><a href="#home" data-toggle="tab"><span class="glyphicon glyphicon-inbox">
</span>Primary</a></li>
<li><a href="#profile" data-toggle="tab"><span class="glyphicon glyphicon-user"></span>
Social</a></li>
<li><a href="#messages" data-toggle="tab"><span class="glyphicon glyphicon-tags"></span>
Promotions</a></li>
<li><a href="#settings" data-toggle="tab"><span class="glyphicon glyphicon-plus no-margin">
</span></a></li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div class="tab-pane fade in active" id="home">
<span th:each="mail : ${emails}" class="list-group">
<a href="#" class="showMail list-group-item">
<span class="glyphicon glyphicon-star-empty"></span>
<span class="name"
style="min-width: 120px; display: inline-block;"
th:text="${mail.shortSender}">WebGoat</span>
<span class="" th:text="${mail.title}">Title</span>
<span class="text-muted" style="font-size: 11px;" th:text="${mail.summary}">- summary</span>
<span class="badge" th:text="${mail.time}">12:10 AM</span>
<span class="pull-right">
<span class="glyphicon glyphicon-paperclip"></span>
</span>
</a>
<!---->
<div class="left15 contents panel panel-default top10" style="display:none" >
<div class="panel-heading" >
<b><span th:text="${mail.title}"></span></b>
<b><span class="pull-right" th:text="${mail.sender}"></span></b>
</div>
<div class="panel-body">
<pre th:utext="${mail.contents}"/>
</div>
</div>
</span>
</div>
<div class="tab-pane fade in" id="profile">
<div class="list-group">
<div class="list-group-item">
<span class="text-center">This tab is empty.</span>
</div>
</div>
</div>
<div class="tab-pane fade in" id="messages">
<div class="list-group-item">
<span class="text-center">Why the name "WebGoat"? Developers should not feel bad about not knowing security. Even the best programmers make security errors. What they need is a scapegoat, right? Just blame it on the 'Goat!</span>
</div>
</div>
<div class="tab-pane fade in" id="settings">
This tab is empty.
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,89 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:replace="fragments/header :: header-css"/>
</head>
<body>
<div th:replace="fragments/header :: header"/>
<div class="container">
<br/><br/>
<fieldset>
<legend th:text="#{register.title}">Please Sign Up</legend>
<form class="form-horizontal" action="#" th:action="@{/register.mvc}" th:object="${userForm}"
method='POST'>
<div class="form-group" th:classappend="${#fields.hasErrors('username')}? 'has-error'">
<label for="username" class="col-sm-2 control-label" th:text="#{username}">Username</label>
<div class="col-sm-4">
<input autofocus="dummy_for_thymeleaf_parser" type="text" class="form-control"
th:field="*{username}"
id="username" placeholder="Username" name='username'/>
</div>
<span th:if="${#fields.hasErrors('username')}" th:errors="*{username}">Username error</span>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('password')}? 'has-error'">
<label for="password" class="col-sm-2 control-label" th:text="#{password}">Password</label>
<div class="col-sm-4">
<input type="password" class="form-control" id="password" placeholder="Password"
name='password' th:value="*{password}"/>
</div>
<span th:if="${#fields.hasErrors('password')}" th:errors="*{password}">Password error</span>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('matchingPassword')}? 'has-error'">
<label for="matchingPassword" class="col-sm-2 control-label" th:text="#{password.confirm}">Confirm
password</label>
<div class="col-sm-4">
<input type="password" class="form-control" id="matchingPassword" placeholder="Password"
name='matchingPassword' th:value="*{matchingPassword}"/>
</div>
<span th:if="${#fields.hasErrors('matchingPassword')}"
th:errors="*{matchingPassword}">Password error</span>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('agree')}? 'has-error'">
<label class="col-sm-2 control-label">Terms of use</label>
<div class="col-sm-6">
<div style="border: 1px solid #e5e5e5; height: 200px; overflow: auto; padding: 10px;">
<p>
While running this program your machine will be extremely
vulnerable to attack. You should disconnect from the Internet while using
this program. WebGoat's default configuration binds to localhost to minimize
the exposure.
</p>
<p>
This program is for educational purposes only. If you attempt
these techniques without authorization, you are very likely to get caught. If
you are caught engaging in unauthorized hacking, most companies will fire you.
Claiming that you were doing security research will not work as that is the
first thing that all hackers claim.
</p>
</div>
</div>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('agree')}? 'has-error'">
<div class="col-sm-6 col-sm-offset-2">
<div class="checkbox">
<label>
<input type="checkbox" name="agree" value="agree"/>Agree with the terms and
conditions
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-6">
<button type="submit" class="btn btn-primary" th:text="#{sign.up}">Sign up</button>
</div>
</div>
</form>
</fieldset>
</div>
</body>
</html>

View File

@ -0,0 +1,56 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<div th:replace="fragments/header :: header-css"/>
</head>
<body>
<div th:replace="fragments/header :: header"/>
<script type="text/javascript" th:src="@{js/fileUpload.js}"></script>
<div class="container">
<div class="alert alert-info fade in">
<a href="#" class="close" data-dismiss="alert">&times;</a>
<p>
Challenges in which you need to call your hacker machine WebWolf offers a simple httpd
server functionality which only logs the incoming request. You can use the following URL:
http://webwolf/landing/* and the incoming request will be available below.
</p>
<p>
This is by no means a substitution of httpd but it offers enough functionality to callback to a safe
environment and does not require you to host your own httpd server on your local machine.
</p>
</div>
<h3>Requests</h3>
<div th:each="trace,iter : ${traces}" class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div class="panel-heading" role="tab" th:id="'heading' + ${iter.index}">
<h4 class="panel-title">
<a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion"
th:href="'#collapse' + ${iter.index}" aria-expanded="false" th:aria-controls="'collapse' + ${iter.index}">
<span th:utext="${trace.date}"/> | <span th:utext="${trace.path}"/>
</a>
</h4>
</div>
<div th:id="'collapse' + ${iter.index}" class="panel-collapse collapse" role="tabpanel"
th:aria-labelledby="'heading' + ${iter.index}">
<div class="panel-body">
<div>
<pre th:utext="${trace.json}"/>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
>
<head>
<title>WebWolf</title>
<link rel="icon" href="/css/img/favicon.ico"/>
<div th:replace="fragments/header :: header-css"/>
</head>
<body>
<div th:replace="fragments/header :: header"/>
<div class="container">
<div class="row" style="margin-top:20px">
<div class="col-xs-12 col-sm-8 col-md-6 col-sm-offset-2 col-md-offset-3" th:style="'background:url(' + @{/images/wolf.png} + ') no-repeat right;'">
<form th:action="@{/login}" method="post">
<fieldset>
<h2>Sign in</h2>
<br/>
<div th:if="${param.error}">
<div class="alert alert-danger">
Invalid username or password.
</div>
</div>
<div th:if="${param.logout}">
<div class="alert alert-info">
You have been logged out.
</div>
</div>
<div class="form-group">
<input type="text" name="username" id="username" class="form-control input-lg"
placeholder="Username WebGoat" required="true" autofocus="true"/>
</div>
<div class="form-group">
<input type="password" name="password" id="password" class="form-control input-lg"
placeholder="Password WebGoat" required="true"/>
</div>
<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6">
<input type="submit" class="btn btn-lg btn-primary btn-block" value="Sign In"/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
</div>
</div>
<!--<div><b><a th:href="@{/registration}" th:text="#{register.new}"></a></b></div>-->
</fieldset>
</form>
</div>
</div>
</div>
<div th:replace="fragments/footer :: footer"/>
</body>
</html>