Medienbildung und Informatik

Folgende Aufgaben haben Programmieranfänger von mir nach ca. vier Einheiten Python bekommen. Das Beispiel zeigt – finde ich – ganz gut, dass Medienkompetenz und Informatik sich sehr gut ergänzen können, teilweise vielleicht sogar einander bedingen. Das Problem der Passwortlänge und dem Passwortaufbau wird hier bewusst nicht angesprochen, weil das programmiertechnisch etwas anspruchsvoller ist. Das kommt dann in der Folgestunde.
Weiterhin ist natürlich auch das sha-2-Verschlüsselungsverfahren moderneren Entwicklungen wie z.B. pbkdf2 weit unterlegen, aber auch programmiertechnisch wesentlich beherrschbarer. sha512 ist schon ganz ok, auch wenn heutige Grafikkarten ca. 200 Millionen Schlüssel pro Sekunde berechnen.

Kryptografie

Immer wieder hörst du davon, dass bei großen Anbietern Datenbankinhalte gestohlen werden. In dem Artikel steht allerdings nichts davon, dass Passwörter gestohlen werden, sondern Hashes. Heute wirst du lernen, dass du jetzt schon ganz einfach viel besser sein kannst als LinkedIn und das mit nur ganz wenigen Codezeilen in Python.

Um alles möglichst gut zu verstehen, musst du auf jeden Fall die beiden oben verlinkten Artikel lesen oder wenigstens überfliegen.

Aufgabe 1:

Nimm eines deiner Passwörter und lasse folgendes Programm laufen (z.B. auf https://try.jupyter.org ).

1
2
3
4
5
6
7
# wir weisen Python an, Kryptografiefunktionen zu laden
import hashlib
# wir fragen nach einem Passwort
crypted_phrase = input()
# Und geben den Hash des Passworts als MD5-Hash aus
print("Hash is:")
print(hashlib.md5(crypted_phrase.encode('utf-8')).hexdigest())

Nimm jetzt den Hash und kopiere ihn auf diese Seite. Nach Eingabe der Sicherheitsabfrage (reCaptcha) kannst du schauen, ob der Hash deines Passworts bereits bekannt ist (Wenn du das Verfahren mit dem Passwort „12345678“ durchführst, wirst du sehen, dass das „geknackt“ wird.

Wiederhole das Verfahren mit einem deiner Passwörter und folgendem Programm (mit „12345678“ klappt es! – auch mit deinem Passwort?):

1
2
3
4
5
6
7
# wir weisen Python an, Kryptografiefunktionen zu laden
import hashlib
# wir fragen nach einem Passwort
crypted_phrase = input()
# Und geben den Hash des Passworts als MD5-Hash aus
print("Hash is:")
print(hashlib.sha512(crypted_phrase.encode('utf-8')).hexdigest())

Wenn dein Passwort auch im zweiten Fall „geknackt“ wurde, hast du ein Problem, wenn du Opfer eines Datenbankdiebstahls wirst. Auch dein Anbieter wird nur Hashes in einer Datenbank speichern.

Informiere dich jetzt über den Unterschied zwischen dem md5- und dem sha512-Verschlüsselungsverfahren. Python kann folgende Verfahren „von Natur aus“: md5, sha1, sha224, sha256, sha384, sha512.

Aufgabe 2:

Das Problem ist schon lange gelöst – mit nur wenigen Codezeilen mehr. Informiere dich über den Begriff „Salt“ in Verbindung mit Hashes.

1
2
3
4
5
6
import hashlib
# Statt "somestring" kannst bzw. solltest du möglichst wirres Zeug hier reinschreiben
salt = "somestring"
crypted_phrase = input()
salted_password = crypted_phrase + salt
print(hashlib.md5(salted_password.encode('utf-8')).hexdigest())

Wenn du jetzt versuchst, den Hash cracken zu lassen, klappt das nicht mehr, weil ein sogenanntest „salt“ (Salz) zum Passwort hinzugefügt wird. Bei unserem Programm verwendet jedes Passwort jedoch den gleichen Salt.

Auch dafür gibt es eine Lösung:

1
2
3
4
5
6
import hashlib, uuid
# Python schreibt nun für dich wirres Zeug hier hinein
salt = uuid.uuid4().hex
crypted_phrase = input()
salted_password = crypted_phrase + salt
print(hashlib.md5(salted_password.encode('utf-8')).hexdigest())

Hätten LinkedIn und andere die Benutzerpasswörter mit einem sicheren Algorithmus (z.B. sha512) gehasht und mit einem Salt versehen, wäre der Diebstahl der Datenbanken nicht so ein großes Problem, da es sehr lange dauern würde, die Passwörter aus den Hashes zu errechnen.

In der Praxis speichert man die Salts im Klartext zusammen mit den Hashes, meist durch ein Trennzeichen abgesetzt. Du kannst ja einmal überlegen, warum das kein Problem darstellt.

Aufgabe 3:

Schreibe folgende Programme

  1. Es wird zweimal ein Passwort abgefragt und dazu ein Hash berechnet. Stimmen beide Hashes (und damit die Passwörter) überein, soll das Programm die Ausgabe „Access granted!“ machen, ansonsten „Access denied!“ ausgeben.
  2. Ein Programm fragt nach einem „Masterpasswort“ (password) und einem Domainnamen (salt). Es berechnet daraus einen Hash, den man als Passwort für die betreffende Webseite benutzen kann – wenn man immer das richtige Masterpasswort und den gleichen Domainnamen eingibt – quasi ein ganz einfacher Passwortmanager!

Über Owncloud mit Quellen syncen, die eigentlich nicht syncen können

Die Möglichkeit, Ordner und Dateien über mehrere Geräte zu synchronisieren, möchte ich nicht mehr missen. Egal ob ich auf der Arbeit, zu Hause oder unterwegs bin – überall habe ich den gleichen Datenbestand.

Wenn ich verschiedene Dienste im Netz nutze, brauche ich meist für jeden eine eigene App bzw. ein eigenes Programm. Einige Dienste scheinen auf den ersten Blick gar keine Synchronisation zu erlauben (z.B. der FTP-Zugang für den Webspace). Dafür gibt es eine Lösung über Owncloud. Owncloud kann nämlich schon sehr lange externe Datenquellen einbinden.

Dazu muss man sich zunächst einmal bei Owncloud als Administrator einloggen und unter Apps auf das +-Zeichen klicken.

owncloud01Danach aktiviert man unter „not enabled“ das Plugin „External Storage“.

owncloud02Anschließend muss man in den Adminbereich gehen

owncloud03… und allen Nutzern erlauben, das Plugin zu nutzen:

owncloud05Dabei sind die unterschiedlichsten Protokolle möglich, z.B. auch andere Owncloudsysteme. Man kann auch globale Ordner definieren, die allen oder nur einigen Nutzern der Owncloud-Instanz zur Verfügung stehen. Anschließend kann sich jeder Nutzer unter dem Menupunkt „Personal“ eigene Datenquellen definieren:

owncloud06Natürlich kann ich auch nur einzelne Ordner der externen Quelle synchronisieren:

owncloud07Owncloud verhält sich gegenüber den externen Quellen wie ein normaler Client, d.h. es werden keine Daten auf dem Owncloudserver gespeichert – er stellt lediglich die Schnittstelle zu anderen Diensten hier.

Der Trick ist, dass ich für alle diese Dienste dann nur noch eine App auf dem Tablet, dem Smartphone oder dem Rechner benötige, um mit ganz unterschiedlichen Quellen Dateien und Daten auszutauschen, auch wenn diese offiziell überhaupt keine Synchronisationsfunktion unterstützen. Diese Dienste erscheinen in der Owncloud-App einfach unter dem Namen, den ich für den Ordner vergeben habe.

Eine Synchronisationsapp für IServ, meinen Landesserver, Google, jeden beliebigen Webspace usw. – reizvoll – oder?

OpenLDAP automatisch installieren und einrichten

Ich habe heute ein Script geschrieben, welches OpenLDAP auf Debiansystemen automatisch installieren und auch gleich für ppolicy konfigurieren kann. Wer sowas schonmal von Hand gemacht hat, weiß um die Schwierigkeiten. Es sollte auf den meisten Debianderivaten funktionieren (entwickelt habe ich auf stretch), ist aber leicht anpassbar, da ich alle Einzelschritte in Funktionen gepackt habe.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#!/bin/bash
 
# globals
LDAPDB="mdb"
PASSWORD="test1234"
HOSTNAME=`hostname`
DOMAIN=`echo  $HOSTNAME | awk -v FS="." '{print $1}'`
TLD=`echo  $HOSTNAME | awk -v FS="." '{print $2}'`
PPOLICY_FILE="/etc/ldap/schema/ppolicy.ldif"
LOGFILE="debug.txt"
 
# basesetup()
# Installs slapd (openLDAP) unattended
# using debconf
 
basesetup() {
 
	PASS=$1
        HOST=$2
	DBTYPE=$3
 
	echo "Building LDAP-Roottree ...\n"
 
	export DEBIAN_FRONTEND=noninteractive
	echo -e " \
		slapd    slapd/internal/generated_adminpw    password   $PASS
		slapd    slapd/password2    password    $PASS
		slapd    slapd/internal/adminpw    password   $PASS
		slapd    slapd/password1    password    $PASS
		slapd	 slapd/backend: string	$DBTYPE
		slapd	 slapd/domain	string	$HOST
	" | debconf-set-selections
 
	apt-get install -y slapd ldap-utils
 
}
 
make_index() {
 
	echo "Adding index ...\n"
 
        echo -e " \
dn: olcDatabase={1}$LDAPDB,cn=config
changetype: modify
add: olcDbIndex
olcDbIndex: mail,givenName eq,subinitial
        " | ldapmodify -Y EXTERNAL -H ldapi:///
 
}
 
# configure_policy()
# installs: 	ppolicy-scheme
# 		ppolicy-module
# 		overlay
# 		ppolicycontext
# 		defaultpolicy
 
configure_policy() {
 
        echo "Setting temporary ACLs ..."
 
        echo -e " \
dn: olcDatabase={1}$LDAPDB,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write by * none
        " | ldapmodify -Y EXTERNAL -H ldapi:///
 
	echo "Adding ppolicy-scheme ..."
 
	ldapadd -Q -Y EXTERNAL -H ldapi:/// -f $PPOLICY_FILE
 
        echo "Activating ppolicy-module ..."
 
        echo -e " \
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: ppolicy.la
        " | ldapmodify -Y EXTERNAL -H ldapi:///
 
	/etc/init.d/slapd restart
 
        echo "Generating ppolicy-context ..."
 
        echo -e " \
dn: ou=policies,dc=$DOMAIN,dc=$TLD
objectClass: organizationalUnit
objectClass: top
ou: policies
        " | ldapadd -Q -Y EXTERNAL -H ldapi:///
 
        echo "Setting default policy ..."
 
        echo -e " \
dn: cn=default,ou=policies,dc=$DOMAIN,dc=$TLD
objectClass: top
objectClass: person
objectClass: pwdPolicy
cn: default
sn: default
pwdAllowUserChange: TRUE
# this don't work though documentation says it should
# pwdAttribute: userPassword
# So we use OID for workaround
pwdAttribute: 2.5.4.35
pwdInhistory: 3
pwdLockout: TRUE
pwdLockoutDuration: 1800
pwdMaxAge: 0
pwdMaxFailure: 3
pwdMinLength: 6
pwdMustChange: TRUE
pwdSafeModify: TRUE
# comment for syntax reason (trailing TAB here leads to syntax error when importing)
        " | ldapadd -Q -Y EXTERNAL -H ldapi:///
 
        echo "Generating overlay ..."
 
        echo -e " \
dn: olcOverlay=ppolicy,olcDatabase={1}$LDAPDB,cn=config
objectClass: olcOverlayConfig
objectClass: olcPPolicyConfig
olcOverlay: ppolicy
olcPPolicyDefault: cn=default,ou=policies,dc=$DOMAIN,dc=$TLD
olcPPolicyHashCleartext: FALSE
olcPPolicyUseLockout: FALSE
olcPPolicyForwardUpdates: FALSE
# comment for syntax reason (trailing TAB here leads to syntax error when importing)
        " | ldapadd -Q -Y EXTERNAL -H ldapi:///
 
}
 
# configure_tls()
# does:
#	generating of cert-authority
#	generating of certs for slapd
#	configuring of slapd for using tls
 
configure_tls() {
 
	echo
 
}
 
# toggle_acl()
# sets ACL back to save values after install
 
toggle_acl() {
 
	echo
 
}
 
# debug_output()
# dumps to file:
#	debconf values for slapd
#	complete Root-DN
#	complete cn=config
 
debug_output() {
 
	debconf-show slapd > $LOGFILE
	slapcat >> $LOGFILE
	ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config >> $LOGFILE
 
}
 
 
# cleanldap()
# Removes all of openLDAP
 
cleanldap() {
 
	apt-get remove -y slapd ldap-utils --purge
 
}
 
# main
 
basesetup $PASSWORD $HOSTNAME $LDAPDB
make_index
configure_policy
debug_output
cleanldap

Eigentlich muss man oben nur ein anderes Passwort setzen und am Ende das „cleanldap“ auskommentieren. Da das Ganze noch „Work in Progress“ ist, fehlen noch einige Funktionen:

  1. Konfiguration für TLS
  2. Integration des freeradius-Schemas
  3. Vernünftige ACLs nach Abschluss der Installation setzen

Ja, ich stehe in diesem Jahr ziemlich auf LDAP …

Lustige Portweiterleitungen

Unsere Schulhomepage besitzt einen eigenen Loginbereich, für den wir gerne auch die Nutzername/Passwortwortkombination nutzen wollten wie für den Schulserver. Mehrere unterschiedliche Zugänge sind in der Regel nutzerunfreundlich und werden kaum akzeptiert.

Das verwendete Joomla! hat zum Glück eine Reihe von Authentifizierungsplugins, unter anderem LDAP, POP3, IMAP oder Keberos. Am einfachsten geht es über IMAP, d.h. Joomla! versucht sich mit den Nutzerdaten bei Mailserver des Schulservers einzuloggen und wenn das klappt, legt es einen neuen Benutzeraccount an, den es zukünftig immer extern authentifiziert. Dummerweise klappte das bei uns nur über eine unverschlüsselte Verbindung zuverlässig – also keine sinnvolle Option.

Glücklicherweise läuft unser Joomla! auf einem VServer, auf den wir Shellzugriff haben. Mit einem linuxtypischen Einzeiler kann man den Mailserverport durch einen verschlüsselten Kanal auf den VServer tunneln – bei uns:

ssh -R 1143:localhost:143 unprivileged@vserver.xy -N -T

Das sorgt dafür, das der unverschlüsselte Mailserverport 143 auf dem VServer unter der Portnummer 1143 erreichbar ist.

Normalerweise würde nach diesem Kommando das Passwort des Benutzer „unprivileged“ (der Nutzer sollte möglichst wenig Rechte auf dem Zielserver haben, weshalb die Portnummer auch größer als 1024 sein muss) erfragt werden. Damit das nicht geschieht, verwenden wir die Authentifizierung per Public-Key.

Unser Schulserver ist nur per VDSL an das Internet angebunden und wird einmal täglich providerseitig vom Netz getrennt. Damit würde unser Tunnel zusammenbrechen. Damit das erkannt wird, läuft folgendes Script per cronjob alle fünf Minuten:

#!/bin/bash
COUNT=`ps aux | grep unprivileged | wc -l`
if [ $COUNT -ge 2 ]; then
exit 0
else
ssh -R 1143:localhost:143 unprivileged@vserver.xy -N -T
fi

Die Variable COUNT enthält die Ausgabe der Befehlspipe zwischen den Backticks `. Wenn der Tunnel offen ist, enthält die Ausgabe zwei Zeilen (den eigentlichen Tunnelprozess und den Suchprozess nach „unprivileged“). Wenn das so ist, tut das Script nichts, wenn nicht, startet es den Tunnel einfach neu. Das Script muss mit Rootrechten laufen, da ein Port unterhalb von 1024 lokal verwendet wird.

Auf diese Weise kann man im Prinzip jeden Dienst lokal auf einen VServer weiterleiten, z.B. auf den LDAP der Musterlösung aus Baden-Württemberg und muss dann keine Klartextpasswörter mehr durch die Gegend schicken.

android_kaputt

Tablets in der Schule: Bitte (fast) keine Androids mehr!

Vorweg

Ich setze persönlich keine Tablets im Unterricht oder meinen eigenen Workflow ein. Für mich persönlich sind das Spielzeuge und keine Arbeitsgeräte. Meine Finger sind zu dick und unmotorisch.

Ich gestalte meinen digitalen Unterricht aber so, dass das Gerät dafür kaum eine Rolle spielt, wenn es zumindest einen Browser und einigermaßen performante Leistungsdaten zum Rendern von Webinhalten verfügt. Meine Tools stellen standardisierte Schnittstellen bereit, sodass hoffentlich jeder die App und das Gerät dafür nutzen kann, die/das zu ihr/ihm passt.

„App“ ist für mich ein anderes Wort für „Programm, dessen Oberfläche auf Touchbedienung zugeschnitten ist“. Damit sind Tablets natürlich willkommen – es gibt ja andere Menschen als mich mit anderen Vorlieben und Präferenzen.

Was ich gar nicht mag, ist als Admin Sonderlösungen bauen zu müssen, weil ein Hersteller meint, eigene „Standards“ seien kundenfreundlicher. Deswegen hasse ich aus Administratorensicht speziell Apple wie die Pest. So viel zum Rant.

Was man in der Schule von der Software eines Gerätes erwarten können muss

 

  1. Regelmäßige Betriebssystemupdates
  2. Regelmäßige Sicherheitsupdates
  3. Verlässliche Sandboxes für Prüfungssituationen
  4. Verlässliches, leicht zu bedienendes MDM (Lösung zum Managen der Geräte, wenn sie schuleigen sind)

… über einen Zeitraum von mindestens fünf Jahren. Ein Hersteller, der das nicht bieten kann, hat nach meiner Meinung in der Schule bei schuleigenen(!) Geräten nichts verloren.

Damit fallen (fast) alle Androidgeräte heraus.

Warum keine Androids?

Das Lizenzmodell von Android ermöglicht erst die Herstellung extrem günstiger Geräte. Die Quelltexte liegen offen, das System lässt sich recht unaufwändig an fast jede beliebige Hardwareumgebung anpassen, d.h. als Hersteller bin ich in der Wahl meiner CPU, meines Grafikprozessors usw. recht frei. Daraus entsteht eine Vielzahl an Produktlinien. Um das System performant und schlank zu halten, bricht man mit einem Grundprinzip von Linux, auf dem Android basiert: Dem generischen System.

Ein generisches System läuft unverändert auf sehr vielen unterschiedlichen Umgebungen: Ubuntu kann ich auf fast jeden Rechner installieren – Linux bringt die dafür erforderlichen Treiber gleich mit und erkennt z.B. Hardware beim Start vollautomatisch.

Ein generisches System kann darüberhinaus zentral geupdatet werden – im Prinzip läuft ja überall das Gleiche. Leider schleppt natürlich ein generisches System alles nur Denkbare an Treibern mit sich und ist daher recht groß – das passt vor allem nicht zu günstiger Hardware.

Kurz gesagt: Bei Androiden muss der Hersteller jedes Sicherheits- und Funktionsupdates für alle seine Produktlinien manuell einpflegen und seinen Kunden z.B. als Betriebssystemimage bereitstellen. Das lohnt sich bei Geräten wie Tablets und Handys mit ohnehin meist kurzer Verwendungszeit in der Regel nicht, sprich:

Die meisten Androidgeräte sind nach recht kurzer Zeit sicherheitstechnisch ein Debakel

Die einzige echte Ausnahme, die ich diesbezüglich kenne, ist die Nexusserie von Google selbst. Meine Nexustablets der ersten Generation erhalten bis heute zeitnah Updates – schon fast vier Jahre mittlerweile.

Man kann ausweichen auf Communities rund um Cyanogenmod – Techies wie ich könnten das ggf.. – aber für Schulen im Allgemeinen ist das keine Option.

In der Schule brauche ich nach meinem Empfinden Geräte, die mindestens drei, besser fünf zuverlässig laufen. Realistisch finde ich eher einen Gerätewechsel nach drei Jahren, d.h. mindestens(!) drei Geräte pro Schullaufbahn, denn schon heute werden die meisten Menschen (auch und gerade SuS!)  Geräte, die noch älter sind, aufgrund des technologischen Wandels als unzumutbar empfinden – daher noch ein Seitenhieb:

Bei Kalkulationen „Tablet preislich gegen Schulbuch / Taschenrechner / Atlas“ ohne Einbezug des technologischen Wandels (Produktupgrade nach drei Jahren) wäre ich SEHR vorsichtig ob des realen Preisvorteils gegenüber heute – unser Wirtschaftssystem basiert nicht darauf, dass wir ständig weniger ausgeben.

 

iPads und Windowstablets 

Apple ist ein in sich geschlossenes System und Microsoft macht den Herstellern seiner Geräte recht rigide Vorgaben, was die Hardwareausstattung angeht – im Prinzip fahren die die generische Strategie des Linuxkernels. Damit ist die Sicherheitsproblematik in einem wesentlichen Kernpunkt entschärft, weil nicht der Hersteller Updates bereitstellt, sondern eben Apple und Microsoft und diese Updates auch über die betriebssystemeigenen Mechanismen installieren. Die damit verbundene Langfristigkeit macht den Einsatz z.B. einer MDM-Lösung oder Klassenraumsteuerung erst beherrschbar: Wenn ich nicht andauernd verseuchte Geräte wiederherstellen und neu in eine MDM-Lösung integrieren muss, wird die Bewältigung des Arbeitspensums möglich. Und gerade Schulgeräte, die durch viele Hände gehen, sind gegenüber derartigen Drangsalierungen extrem gefährdet. Selbst Apple hat mittlerweile kapiert, dass ein 1:1-Design eben nicht in eine 1:many-Umgebung passt und entwickelt in die richtige Richtung.

Nachtrag:

Etwas ausführlicher hat sich Andreas Hofmann mit der neuen Initiative von Apple beschäftigt.

 

Anfangsgenölewiederaufgriff

Mir ist völlig klar, dass mit der automatischen Updatepolitik von Apple und gerade auch Microsoft auch sehr streitbare Mechanismen Einzug in die mobilen Geräte halten – vor allem vor dem Datenschutzhintergrund. Mir wäre ein Ubuntu-Touch auf freier Hardware ohne UEFI- und TPM-Mist bedeutend lieber.

Da wir aber im „Isnummalsoland“ leben, geht es um pragmatische Ansätze. Und da hat Apple schon aufgrund des Appangebot im Vergleich zu Microsoft zurzeit die Nase für viele Anwender halt vorne. Ich persönlich finde das doof.

Vielleicht fehlt es bei Androids einfach auch nur an Dienstleistern, die das Ganze z.B. mit Cyanogenmod schlicht professionalisieren und Servicebundles für drei bis fünf Jahre anbieten.

1 2 3 21