=Paper=
{{Paper
|id=None
|storemode=property
|title=Sicherheitsimplikationen beim Einsatz von Test Doubles zur automatisierten Bewertung studentischer Java-Programme mit Graja und mockito
|pdfUrl=https://ceur-ws.org/Vol-1067/abp2013_submission_1.pdf
|volume=Vol-1067
|dblpUrl=https://dblp.org/rec/conf/abp/Garmann13
}}
==Sicherheitsimplikationen beim Einsatz von Test Doubles zur automatisierten Bewertung studentischer Java-Programme mit Graja und mockito==
Sicherheitsimplikationen beim Einsatz von Test Doubles
zur automatisierten Bewertung studentischer Java-
Programme mit Graja und mockito
Robert Garmann
Hochschule Hannover
Fakultät IV - Wirtschaft und Informatik
Ricklinger Stadtweg 120
30459 Hannover
robert.garmann@hs-hannover.de
Zusammenfassung setzt, die z. B. mittels der Bibliothek mockito [Ka13] erstellt wer-
Wir demonstrieren, dass der Einsatz von Test Doubles bei der den. An einer Beispielaufgabe verdeutlichen wir in Abschnitt 2,
automatisierten Bewertung studentischer Java-Programme wie der JUnit-basierte Autobewerter Graja und mockito zur Be-
besondere Sicherheitsfragen aufwirft. Wie skizzieren kurz eine obachtung interner Programmschnittstellen genutzt werden
mögliche Antwort auf diese Fragen. können.
Das studentische Programm wird bei der dynamischen Analyse
Im ersten Teil demonstrieren wir die Erstellung eines sog.
ausgeführt. Sicherheitsmaßnahmen auf dem Bewertungsrechner
AssignmentGraders, der in der Lage ist, interne Programm-
sind notwendig, um ungewolltes oder böswilliges Fehlverhalten
schnittstellen eines maschinell zu bewertenden Java-Programms
des studentischen Programms zu unterbinden. In Abschnitt 3
zu beobachten. Beispielhaft nutzen wir den Autobewerter Graja in
stellen wir das betrachtete Modell eines Bewertungssystems vor
Verbindung mit mockito Test Doubles. Wir zeigen, wie man
und diskutieren relevante Sicherheitsaspekte.
Leistungsaspekte einer studentischen Lösung einzeln und gezielt
automatisiert bewertet. Bei einer Beschränkung auf die Bibliotheken wie mockito wurden nicht für die automatisierte
Beobachtung externer Programmschnittstellen würden sich diese Programmbewertung entworfen. Die Sicherheit der
Aspekte der gezielten Bewertung entziehen. Im zweiten Teil Testumgebung spielt beim (Regressions-)Test großer
beleuchten wir Bedrohungen des das zu bewertende Programm Softwaresysteme meist eine untergeordnete Rolle. Im
ausführenden Systems und gewichten ausgewählte Ursachen. Wir Bewertungsszenario jedoch wirft der Einsatz einer solchen
konzentrieren uns auf Bedrohungen, die mit Mitteln der Java-2- Bibliothek essentielle Sicherheitsfragen auf, für die wir in
Sicherheitsarchitektur beherrschbar sind und liefern einige Abschnitt 4 eine mögliche Lösung vorstellen.
Beispiele zur Abgrenzung. Die Eigenheiten der Java-2-
Sicherheitsarchitektur werfen im Kontext des Test Double
2. Beobachtung programminterner
Einsatzes Fragen auf, die wir im dritten Teil erörtern. Test Schnittstellen
Doubles sollten in einem anderen Schutzbereich der Java-2- Die Frage, wann ein studentisches Programm gut ist, ist nicht
Sicherheitsarchitektur als der studentische Code liegen. Um eine leicht zu beantworten. Neben dem Kriterium der funktionalen
privilegierte Ausführung der Test Doubles auch dann zu forcieren, Korrektheit muss das Programm nichtfunktionale Kriterien
wenn der Aufruf aus studentischem Code erfolgt, schlagen wir erfüllen (Effizienz, Änderbarkeit, …). Einige dieser Kriterien
den Einsatz von Proxy-Objekten vor. Um auch Nicht-Spezialisten lassen sich recht gut automatisiert untersuchen. Grundsätzlich gibt
der beschriebenen Sicherheitsbelange die Autorenschaft von es zwei Herangehensweisen bei der maschinellen Untersuchung
AssignmentGradern zu ermöglichen, entwickeln wir eine eines Bewertungsobjektes [SL05]: die statische Code-Analyse
Wrapper-Bibliothek für mockito, deren zentrale Entwurfsideen (bspw. in [SBG10]) und die dynamische Code-Analyse (bspw. in
wir kurz skizzieren. [KSZ02], [Ed03]). In diesem Aufsatz befassen wir uns mit der
letztgenannten Herangehensweise, der Beobachtung des
1. Einleitung Verhaltens eines studentischen Java-Programms durch Tests.
Automatisierte Bewertung studentischer Programme wird in der
Informatik-Lehre zurzeit überwiegend im formativen Assessment Bei der dynamischen Code-Analyse beobachtet man das
eingesetzt. Zeit- und ortsunabhängiges, maschinell erstelltes, Laufzeitverhalten des Bewertungsobjekts an beobachtbaren
quantitatives und qualitatives Feedback soll Studierende in die Schnittstellen. Hervorragend geeignet für die Überprüfung der
Lage versetzen, ihre (Teil-)lösungen zu Programmierübungen funktionalen Korrektheit des Bewertungsobjekts sind Ein- und
schrittweise zu verbessern. Ausgabeschnittstellen des Benutzers, die auch leicht einer
maschinellen Bedienung bzw. Abfrage zugänglich sind.
Studentische Programme müssen funktionale und nichtfunktionale Interessante Schnittstellen für die Bewertung des studentischen
Anforderungen erfüllen, die mit statischen oder dynamischen Programmverhaltens sind u. a.1 Tastatureingabe, Consolenaus-
Analyseverfahren untersucht werden können. Für die Analyse der gabe, Mauseingabe, GUI-Ausgabe [TE08], Kommandozeilen-
„inneren Qualität“ des Bewertungsobjekts spielt die dynamische argumente beim Programmstart, Dateiein-/-ausgabe. Allen
Analyse an internen Programmschnittstellen (Methodenaufruf) genannten Schnittstellen gemein ist, dass sie prinzipiell auch vom
eine wichtige Rolle. Unittest-Frameworks wie JUnit wurden dazu
entwickelt, kleinste Einheiten eines Testobjekts durch 1
Methodenaufruf und Verifizierung des Ergebnisses dynamisch zu Über diese nicht abschließende Aufzählung hinaus sind selbst-
untersuchen. Um die zu untersuchende Einheit für die Dauer des verständlich viele weitere Schnittstellen denkbar (Umgebungs-
Tests vom Restsystem zu isolieren werden Test Doubles einge- variable, Audio/Video, Netzwerk, etc.).
Benutzer des studentischen Programms bedient werden können. Berechnen Sie die Länge der Hypotenuse eines rechtwinkligen
Um ein Bewertungsobjekt nun automatisiert mit Eingaben über Dreiecks. Teilen Sie den Programmcode auf zwei Klassen auf:
die genannten Schnittstellen zu versorgen und die Ausgaben ma- QuadratImpl implementiere das folgende vorgegebene
schinell auszuwerten, werden Autobewerter wie der hier Interface:
eingesetzte Graja [St13] verwendet. package de.hsh.prog;
public interface Quadrat {
Ein automatisiertes Bewertungsverfahren nimmt bei Nutzung der double quadrat(double v); // berechnet v²
oben genannten Schnittstellen das Bewertungsobjekt als „black }
box“ wahr und kann wenig über die Qualität der inneren Struktur Schreiben Sie eine weitere Klasse Hypo mit einer statischen
des Bewertungsobjekts erfahren. Gut überprüfbar ist die Methode hypo, die als ersten Parameter ein Quadrat-Objekt und
funktionale Korrektheit und die Überprüfung einiger als zwei weitere Parameter die Längen zweier Katheten erhält.
nichtfunktionaler Eigenschaften (z. B. Ressourcenverbrauch). Um Gewünschter Rückgabewert ist die Länge der Hypotenuse.
mehr über die „innere Qualität“ des Bewertungsobjekts zu Quadrierungen soll hypo an das Quadrat-Objekt delegieren.
erfahren, ist es hilfreich, das studentische Programm an internen
Abbildung 1: Stark vereinfachte Beispielaufgabe
Programmschnittstellen zu beobachten. Eine geeignete
Schnittstelle ist der Methodenaufruf mit Methodenparametern als 2.3 Bewertung mit Graja
Eingabe und Methodenrückgabe als Ausgabe. Den Bewertungsaspekt (1) überprüft der in Abbildung 2 dar-
Im Folgenden geben wir einen kurzen Überblick über die gestellte, mit Graja kompatible Code.
Funktionen von Graja und stellen eine Beispielaufgabe vor. Der Aufruf der internen Programmschnittstelle des studentischen
Danach zeigen wir, wie studentische Lösungsversuche für diese Codes ist in Programmzeile 06 zu finden. Davor wird eine Instanz
Aufgabe mit Graja unter Einsatz von Test Doubles bewertet der studentischen Klasse erzeugt und danach das beobachtete
werden können. Ergebnis überprüft. Diese Art von Bewertungscode ist dem in der
2.1 Graja professionellen Softwareentwicklung verbreiteten Testcode für
Modultests sehr ähnlich. Spezialitäten der hier betrachteten
Graja (“Grading Java programs”) ist i. w. ein Überbau über dem
Programmbewertung sind die in Zeile 01 vergebenen Teilpunkte
JUnit2-Testframework und hat seine Charakterzüge von seinem
und der in Zeile 08f zu findende ausführliche Fehlerhinweis.
Vorbild WebCAT [Ed03] geerbt. Graja bietet u. a. folgende
Weiterhin besonders ist die von Graja angebotenen Reflection-
Funktionen:
Bibliothek (Zeile 04f), die etwaige Exceptions in verständliche
Extrahieren und Übersetzen von Code aus einem ZIP-Archiv, Fehlermeldungen verwandelt.
Umleitung von Standard-Ein/Ausgabeströmen zur Verein-
01 @Test @ScoringWeight(35.0)
fachung der maschinellen Steuerung des Bewertungsobjekts, 02 public void pruefeQuadratMethode() {
intelligente Vergleiche von erwarteter und beobachteter Aus- 03 double a= 3, expected= a*a;
gabe eines Bewertungsobjekts, 04 Quadrat studentImpl= ReflectionSupport.create(
05 getSubclassForName("QuadratImpl",Quadrat.class));
bequeme „reflection“-basierte Analyse studentischen Codes, 06 double observed= studentImpl.quadrat(a);
Generierung formatierter, zielgruppenorientierter, und nach 07 org.junit.Assert.assertEquals(
Kritikalität abgestufter Bewertungskommentare, 08 "quadrat("+a+")="+observed+" (erwartet :"+expected
09 +")", expected, observed, 1E-5);
abgestufte Punktevergabe für verschiedene vom Dozenten 10 }
festzulegende Bewertungsaspekte,
Übersetzung und Ausführung von „on the fly“ generiertem Abbildung 2: Bewertung des Aspekts (1)
Java-Code während der Bewertung,
11 @Test @ScoringWeight(25.0)
Begrenzung der genutzten Systemresourcen (Laufzeit, 12 public void pruefeGesamtfunktion() {
persistenter Speicherplatz, Hauptspeicher), 13 double a=3, b=4, cExpected=5;
Ausführung des studentischen Codes und des 14 Quadrat stub= Mockito.mock(Quadrat.class);
15 Mockito.when(stub.quadrat(a)).thenReturn(a*a);
Bewertungscodes in verschiedenen, separat abgesicherten 16 Mockito.when(stub.quadrat(b)).thenReturn(b*b);
Schutzbereichen. 17 double c= ReflectionSupport.invokeStatic(
18 getClassForName("Hypo"),double.class,"hypo",stub,a,b);
19 org.junit.Assert.assertEquals("hypo(q,"+a+","+b+")="+c+
2.2 Beispielaufgabe 20 " (erwartet: "+cExpected+")", cExpected, c, 1E-5);
Wir betrachten eine für Zwecke der konzentrierten Darstellung 21 }
stark vereinfachte Programmieraufgabe (s. Abbildung 1).
Abbildung 3: Bewertung des Aspekts (2)
Diese Aufgabe verlangt vom Studierenden nicht nur die
Programmierung einer einfachen mathematischen Formel, 22 @Test @ScoringWeight(40.0)
23 public void pruefeAufrufVonQuadrat() {
sondern die Implementierung einer vorgegebenen Schnittstelle.
24 double a=3, b=4;
Eine korrekte Lösung kann nicht nur Hypotenusen berechnen (2); 25 Quadrat mock= Mockito.mock(Quadrat.class);
eine korrekte Lösung kann darüber hinaus Quadrate berechnen (1) 26 ReflectionSupport.invokeStatic(
und sie setzt Wiederverwendung durch Delegation ein (3). Für 27 getClassForName("Hypo"),double.class,"hypo",mock,a,b);
28 try {
jeden der im vorstehenden Satz markierten Bewertungsaspekte 29 Mockito.verify(mock, Mockito.times(1)).quadrat(a);
möchten wir Teilpunkte vergeben. 30 Mockito.verify(mock, Mockito.times(1)).quadrat(b);
31 } catch (WantedButNotInvoked e) {
32 org.junit.Assert.fail("hypo muss die Quadrierung "+
33 "an den Quadrat-Parameter delegieren");
34 }
35 }
2
http://junit.org/ Abbildung 4: Bewertung des Aspekts (3)
2.4 Test Doubles: Stubs und Mocks AutograderCore: Der Kern des Autobewerters, welcher eine
Ähnlich ließe sich nun der Bewertungsaspekt (2) untersuchen, Startroutine und eine Bibliothek mit bewertungs-
indem eine QuadratImpl-Musterlösung als Parameter an die unterstützenden Funktionen enthält. Ein Beispiel einer
studentische hypo-Methode übergeben wird. Die erneute AutograderCore-Komponente ist Graja.
Verwendung einer u. U. fehlerhaften studentischen QuadratImpl- AssignmentGrader: vom Dozenten erstellter, auf eine
Klasse würde die Bewertung des Aspekts (2) negativ verzerren. spezielle Programmieraufgabe zugeschnittener Code (kann
Der Fehler würde in zwei Bewertungsaspekten „gezählt“. Fremdsoftware, bspw. die mockito-Bibliothek beinhalten).
Die Codeschnipsel der Abschnitte 2.3 und 2.4 entstammen
Als Alternative zu einer eigenen Musterlösung kann man ein Test dieser Komponente.
Double [Me07] einsetzen – ein Platzhalter-Objekt, mit dem ein
Submission: vom Studenten erstellter Lösungsversuch.
untersuchter Programmteil (das sog. system under test - kurz SUT)
während des Tests interagiert. Stub-Objekte sind Test Doubles, Jede Komponente5 stellt einen eigenen Schutzbereich (protection
die vorgefertigte Antworten an das SUT liefern. domain) mit jeweils eigenen Rechten (permissions) dar.
Der Code in Abbildung 3 verwendet in Zeile 14 die Bibliothek
mockito3 zur Erzeugung eines Stubs, welches das Interface
Quadrat vollständig implementiert. Die beiden folgenden Zeilen
„bestücken“ das Stub mit vorbereiteten Antworten auf erwartete
Anfragen des SUT4. In Zeile 17f kommt das SUT (hier die Abbildung 5: Drei geladene Komponenten
studentische Methode hypo) zur Ausführung. Als Übergabe- 3.2 Benötigte Rechte
parameter erhält hypo das Stub-Objekt.
Der AutograderCore benötigt für seine Funktion weitgehende
Der Bewertungsaspekt (3) lässt sich schließlich durch eine weitere Rechte (Zugriffe auf das lokale Dateisystem, Ausführen des
Test Double Variante, die sog. Mock-Objekte realisieren (vgl. Compilers, Verwendung eigener Klassenlader, Zugriff auf
Abbildung 4). Ein Mock-Objekt wird in Zeile 25 erstellt, welches Reflection-Funktionen, etc.). Die Submission benötigt in der
die Quadrat-Schnittstelle implementiert. Da uns bei diesem Regel wenige Rechte, wobei dies sicher von der Art der zu
Bewertungsaspekt das Berechnungsergebnis nicht interessiert, lösenden Programmieraufgabe abhängt. Dazwischen im Sinne der
programmieren wir keine vorbereiteten Antworten. Stattdessen Rechtemenge steht der AssignmentGrader, der häufig grund-
befragen wir das Mock-Objekt nach Ausführung des SUT in Zeile legende Rechte für Dateizugriffe, manchmal auch weitergehende
29f, ob es Aufrufe mit den angegebenen Parametern erhalten hat. Rechte besitzen muss. Eine Teilmengenbeziehung zwischen den
benötigten Rechtemengen der drei genannten Schutzbereiche
3. Sicherheit des Bewertungssystems besteht nicht notwendigerweise.
Der Ansatz, studentische Lösungen dynamisch zu analysieren,
erfordert die Ausführung des studentischen Codes. Im Unter- 3.3 Bedrohungspotential
schied zu herkömmlichen Software-Tests, wo Tester und Autor Um das Bedrohungspotential6 der einzelnen Komponenten
einander vertrauen (bei Unit-Tests oft sogar dieselbe Person sind), einschätzen zu können, betrachten wir zunächst die in Tabelle 1
wo also die Testumgebung vom zu testenden System kein böswil- aufgeführten Merkmale der Komponenten-Autoren. Die beiden
liges Verhalten zu befürchten hat, ist dies beim Test von studen- ersten Merkmale begünstigen bei hoher Ausprägung unabsichtlich
tischen Einreichungen anders. Hier muss mit Angriffen des getes- herbeigeführte Bedrohungen, das dritte Merkmal begünstigt
teten Codes auf die Testumgebung gerechnet werden. Einige An- absichtlich herbeigeführte Bedrohungen, das vierte Merkmal
griffsbeispiele stellt Abschnitt 3.4 vor. Dazu kommen unab- begünstigt jede Art von Bedrohung.
sichtliche Programmierfehler in weitaus größerem Umfang als bei
Tabelle 1: Betrachtete Merkmale der Komponenten-Autoren
Tests professioneller Software. Schutzmaßnahmen gegen solche
Ausprägungs-
Angriffe sind daher unabdingbar. In diesem Abschnitt wollen wir
grad7 für …
Assignment-
Autograder-
Submission
konkrete Bedrohungen und Gegenmaßnahmen beleuchten.
Grader
Core
3.1 Schutzbereiche
Als Bewertungssystem betrachten wir einen separaten Betriebs- Nr. Merkmal
systemprozess. Aus konzeptioneller Sicht lädt der Prozess drei
verschiedene Komponenten und führt sie aus (vgl. Abbildung 5). 1 Geringe Programmiererfahrung - - +
Wir gehen davon aus, dass alle Komponenten aus Java Bytecode 2 Geringe Bereitschaft, Zeit für die korrekte Pro-
- 0 +
bestehen, die von derselben JVM-Instanz geladen werden: grammierung der Komponente aufzuwenden
3 „Kriminelle Energie“, d. h. Bereitschaft,
- - +
3 Bedrohungen absichtlich herbei zu führen.
http://code.google.com/p/mockito/
4 Größe der Autorengruppe - 0 +
4
Zur Funktionsweise der auf der ersten Blick verwirrenden
Aufrufsyntax folgt eine kurze Erläuterung: Mockito.mock erzeugt Vor diesem Hintergrund erwarten wir von der Submission-Kom-
ein Objekt einer zur Laufzeit mit cglib (http://cglib.sourceforge. ponente das größte Bedrohungspotential. Die AssignmentGrader-
net/) erzeugten Subklasse von Quadrat. Das wie ein normaler
Methodenaufruf aussehende stub.quadrat(a) führt mockito- 5
In der Praxis entspricht jede Komponente einem jar-Archiv oder
intern dazu, dass eine ID des aktuell ausgeführten Threads in jeweils einer Menge von jar-Archiven. Jedem jar-Archiv wird
einer Datenstruktur zusammen mit dem stub-Objekt und dem ein Satz von Rechten zugeordnet.
Wert a abgelegt wird. Der Rückgabewert von stub.quadrat(a) 6
wird zwar an Mockito.when weiter gereicht, dort jedoch nicht Wir meinen hiermit das, was in etablierten Risikoschätzme-
ausgewertet. Stattdessen weist die ID des aktuell ausführenden thoden wie [oV13] „likelihood“ genannt wird.
7
Threads den Weg zum soeben abgelegten stub-Objekt. Legende: -=gering, 0=mittel, +=hoch
Komponente, die in der Regel von Lehrkräften oder Hilfspersonal 3.4.2.1 „rm –rf /“
erstellt wird, ist weniger kritisch, den AutograderCode erachten Ein bösartiges Beispiel für Submission-Code, welcher versucht,
wir als Komponente mit dem geringsten Bedrohungspotential. alle Dateien im Dateisystem zu löschen:
3.4 Bedrohungen im Einflussbereich des Java Runtime.getRuntime().exec("rm –rf /");
Securitymanagers Durch Gewährung selektiver Dateizugriffsrechte mittels der Java
Uns interessieren ganz allgemein alle Bedrohungen der Vertrau- Sicherheitsarchitektur oder auch mittels der vom Betriebssystem
lichkeit und Integrität der Daten auf dem die JVM beherbergen- verwalteten Dateirechte kann dieser Angriff gut abgewehrt wer-
den System (Dateien, Nutzerdaten, Musterlösungen, …), sowie den.
alle Bedrohungen der Verfügbarkeit des Bewertungsdienstes. Wir 3.4.2.2 Denial of service
wollen mit der Bedrohungsanalyse dieses Kapitels keine konkret Ein anderes Beispiel, das versucht Schaden anzurichten, in dem es
auszumerzenden Schwachstellen identifizieren, sondern es soll die Festplatte füllt10:
hier darum gehen, einige mögliche Angriffe mit ihren
FileOutputStream f=new FileOutputStream("x");
Auswirkungen („impacts“) zu benennen, die genügend Motivation while (true) f.write(42);
liefern, um den Einsatz des Java Securitymanagers für sinnvoll zu
erachten. In der folgenden Darstellung nehmen wir die zu Wenn wir davon ausgehen, dass Submission-Code in wenigstens
motivierende Maßnahme vorweg: den Einsatz des Security- einem Verzeichnis Schreibrechte eingeräumt werden müssen, ist
managers. Die Motivation der Maßnahme durch Angriffsbeispiele dieser denial of service Angriff mit Mitteln der Java Sicher-
folgt in Abschnitt 3.4.2. heitsarchitektur unseres Wissens nicht abwehrbar. Hier müssen
dem die JVM beherbergenden Betriebssystemprozess Ressourcen
3.4.1 Einsatz der Java Sicherheitsarchitektur in begrenztem Maße zugeteilt werden. Beispielsweise in Form
Konkret wollen wir dem Submission-Schutzbereich Rechte einer separaten Festplattenpartition oder in Form einer Datei
erteilen oder entziehen, die der Menge aller durch die Java begrenzter Größe, die als loopback device verwendet wird.
Sicherheitsarchitektur definierten Rechte entnommen werden. Ein
Ähnlich müssen die Ressourcen Hauptspeicher und CPU-Zeit
paar Beispiele seien hier genannt8:
durch die Umgebung der JVM begrenzt werden, etwa über einen
PropertyPermission: Auslesen oder Setzen von Umgebungs- Parameter zum maximalen Speicherverbrauch beim JVM-Start
informationen (bspw. mag eine Submission berechtigter- bzw. mit Hilfe des Linuxkommandos timeout.
weise das auf dem System gebräuchliche Zeichen für den
Zeilenumbruch abfragen wollen - line.separator) 3.4.2.3 „/etc/passwd“
FilePermission: Dateizugriffsrechte (bspw. Einlesen und Es folgt ein Beispiel, das versucht, die Liste der Benutzernamen
Schreiben von Dateien im Arbeitsbereich der Submission) des Systems auszuspähen:
SocketPermission: Netzzugriffsrechte (bspw. soll die Sub- System.out.println(Files.readAllLines(new File("/etc/passwd").
toPath(), Charset.forName("UTF-8")));
mission auf eine im Netz vorgehaltene Datenbank zugreifen)
ReflectPermission: potentes Recht zur Überwindung der Da die Datei /etc/passwd i. d. R. für jeden Systemnutzer lesbar ist,
private/protected-Kapselung (wird der Submission i. d. R. können vom Betriebssystem verwaltete Dateirechte nicht greifen.
entzogen; Begründung am Beispiel in Abschnitt 3.4.2.5) Dies ist eine Bedrohung, die durch selektive Rechte gemäß der
RuntimePermission: diverse potente Rechte vom Nachladen Java Sicherheitsarchitektur abwehrbar ist.
weiterer Klassen bis zur Umleitung der Ein-/Ausgabe (für 3.4.2.4 Ausspähen der Musterlösung
Submission i. d. R. nicht erforderlich und damit entziehbar) Ist etwa der Klassenname einer Musterlösung, die häufig Teil der
AssignmentGrader-Komponente ist, bekannt oder erraten worden,
Viele Bedrohungen können durch die Java Sicherheitsarchitektur könnte man wie folgt versuchen, an den Bytecode der
kontrolliert werden. Insbesondere gegen unabsichtlich Musterlösung zu kommen:
herbeigeführte Bedrohungen ist das Sandbox-Prinzip der Java
InputStream is= Class.forName("org.domain.sample.Solution").
Sicherheitsarchitektur ein wirksamer Mechanismus. Absichtlich getResourceAsStream("Solution.class");
herbeigeführte Bedrohungen können nicht völlig9 durch die Java int b; while ((b= is.read()) >= 0) System.out.print(b+" ");
Sicherheitsarchitektur unterbunden werden, wie die Beispiele des
Die Standardausgabe wird dem Autor der Submission i. d. R. zur
folgenden Abschnitts zeigen sollen.
Erläuterung der Bewertung angezeigt.
3.4.2 Beispiele absichtlich herbeigeführter Dieser Angriff ist leicht mit Mitteln der Java
Bedrohungen Sicherheitsarchitektur abwehrbar, indem das Recht zum Einlesen
Zur Ein- und Abgrenzung seien einige ganz konkrete Beispiele für des AssignmentGrader-jar-Archivs nicht gewährt wird.
absichtlich herbeigeführte Bedrohungen genannt. Diese Liste ist
verständlicherweise nicht erschöpfend. Sie soll über die Liste des 3.4.2.5 Ausführen der Musterlösung
Abschnitts 3.4.1 hinaus einen Eindruck davon vermitteln, welche Die Submission könnte versuchen, die Musterlösung einfach
Bedrohungen allein mit Mitteln der Java Sicherheitsarchitektur auszuführen und dadurch die generierten Ausgaben als die
abwendbar sind und welche zusätzliche Maßnahmen erfordern. eigenen zu „verkaufen“. Dieser Angriff lässt sich abwehren,
Die Beispiele geben außerdem einen Eindruck des möglichen indem die Musterlösungsklasse als package private deklariert wird
„impact“ [oV13] erfolgreicher Angriffe. und indem Submission-Code das Recht zur Überwindung der
Package-Kapselung nicht erhält.
8
Weitere s. z. B. http://docs.oracle.com/javase/7/docs/technotes/
guides/security/permissions.html
9 10
Noch dazu muss immer wieder mit neu entdeckten Sicher- Bei diesem Beispiel kann es sich auch um eine unabsichtlich
heitslücken in der Java Sandbox gerechnet werden. herbeigeführte Bedrohung handeln.
4. Test Doubles bei aktivem Securitymanager in Java den doPrivileged-Aufruf. Ein solcher Aufruf wirkt als Ab-
Das vorangegangene Kapitel hat motiviert, dass der Einsatz der bruchskriterium bei der Bildung der o. g. Rechte-Schnittmenge.
Java Securitymanagers sinnvoll ist, um reale Bedrohungen Oberhalb des doPrivileged-Aufrufs am Aufrufstapel beteiligte
abzuwenden. Die durch den Einsatz des Securitymanagers Schutzbereiche werden nicht berücksichtigt.
resultierenden Auswirkungen auf den Einsatz von Test Doubles Wäre etwa im Beispiel der Abbildung 6 der Aufruf der Methode d
sind Gegenstand des nun folgenden Kapitels. ein privilegierter Aufruf, würde die resultierende Schnittmenge
die Rechte {2, 4} umfassen.
4.1 Wirkung der Schutzbereiche zur Laufzeit
Die drei in Abschnitt 3.1 eingeführten Schutzbereiche werden 4.2 Sicherheitsimplikationen durch Test
üblicherweise der Klasse der Anwendungsbereiche (application Doubles
domains) zugeordnet. Ein vierter Schutzbereich mit i. d. R. unein- Beim Einsatz von Test Doubles ruft Submission-Code Test
geschränkten Rechten ist der Systembereich (system domain), Doubles des AssignmentGrader-Schutzbereichs auf (vgl. Aufruf
dem u. a. die Klassen der Java-Standardbibliothek angehören. der Methode h in Abbildung 7). Ohne besondere Vorkehrungen
Bei eingeschaltetem Securitymanager prüft die JVM zur Laufzeit würde der Code im Test Double mit den Rechten der Schnittmen-
alle an der aktuell aufzurufenden Operation beteiligten ge (AutograderCore ∩ AssignmentGrader ∩ Submission) aus-
Komponenten auf dem Aufrufstapel. Programmcode eines einge- geführt, also der Rechtemenge {4}. Der von mockito erzeugte
schränkten Anwendungsbereichs darf durch Aufruf einer Bytecode eines Test Doubles ruft jedoch Methoden der mockito
Operation des Systembereichs selbstverständlich keine zu- Bibliothek auf (Methode i), die weitgehende Rechte erfordern,
sätzlichen Rechte erlangen. Die JVM ermittelt daher die u. a. das sehr potente Recht java.lang.reflect.ReflectPermission
Schnittmenge der Rechte aller am Aufrufstapel beteiligten "suppressAccessChecks", welches den Zugriff auf private und pro-
Schutzbereiche, um eine potentiell bedrohliche Operation zu tected member einer Klasse erlaubt (in Abbildung 7 in der Spalte
überprüfen [Go13]. Die Aufrufreihenfolge zur Laufzeit ist in der „Recht 5“ vorstellbar).
Regel11 AutograderCore → AssignmentGrader → Submission Eine Lösung kann nun nicht sein, dem Submission-Schutzbereich
(vgl. Abbildung 6). Mit zunehmender Aufruftiefe stehen geringere alle Rechte zu gewähren, die das Test Double benötigt. Min-
Rechte zur Verfügung. destens das Beispiel in Abschnitt 3.4.2.5 spricht dagegen. Wäre
der Aufruf der Methode h privilegiert, würden die Methoden h
Recht 1
Recht 2
Recht 3
Recht 4
Recht 5
Komponente Aufrufstapel
und i mit der Rechtemenge {2, 4, 5} ausgeführt. Leider hat der
Autor des AssignmentGraders keine Möglichkeit, den Test
Autograder- a Double-Aufruf privilegiert zu gestalten. Die Programmierschnitt-
Code b stelle von mockito, wie wir sie in Abschnitt 2.4 kennen gelernt
Assignment-
c haben, ermöglicht keine privilegierten Test Doubles. Der eigent-
d liche Methodenaufruf findet im Submission-Code statt, der nicht
Grader e
im Einflussbereich des AssignmentGrader-Autors steht.
f
Submission g
Resultierende Schnittmenge:
Legende: Aufruf: Methode: Recht:
Abbildung 6: Aufrufstapel und resultierende Rechte (Beispiel)
Recht 1
Recht 2
Recht 3
Recht 4
Recht 5
Komponente Aufrufstapel
Autograder- a Abbildung 8: Proxy-Klasse für ein Test Double von Quadrat
Code b Die vorgeschlagene Lösung besteht nun darin, eine Proxy12-
c
Assignment- i Klasse in der AssignmentGrader-Komponente zu erstellen, die ein
d
Grader e
h Test Double umhüllt. Beispielhaft ist in Abbildung 8 das Quadrat-
f Interface und das zugehörige, mit Mockito.mock erzeugte Test
Submission g Double13 zu sehen.
Die Proxy-Klasse besitzt genau die gleiche Schnittstelle wie das
Resultierende Schnittmenge:
Original (Quadrat) und eine dauerhafte Referenz zum Test Double
Objekt. Die Implementierung der quadrat-Methode der Proxy-
Legende Methode d. Test Doubles:
Klasse besteht nun aus einem privilegierten Aufruf von
Abbildung 7: Privilegierter Callback eines Test Doubles TestDouble.quadrat.
Damit Code des Systembereichs Rechte (bspw. Einlesen von
Font-Dateien zwecks Erzeugung einer Ausgabe) erhalten kann,
12
die aufrufender Anwendungsbereichs-Code nicht besitzt, gibt es http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Pro
xy.html
11 13
Rückwärts gewandte Aufrufe von Methoden des Autograder- Der von mockito erzeugten Klasse haben wir hier für Darstel-
Core aus dem AssignmentGrader heraus sind ebenfalls denkbar, lungszwecke einen Namen gegeben. In Wirklichkeit ist die
sind jedoch hier nicht Gegenstand der Betrachtung. erstellte Klasse aus Benutzersicht anonym.
Den wenigsten Autoren von AssignmentGradern wird die 5. Fazit
Sicherheit des Autobewerters so wichtig sein, dass sie die Mühe Wählt man wie in Graja JUnit-Tests als Werkzeug zur
auf sich nehmen und eine Klasse Proxy für jeden zu automatisierten Programmbewertung, ist der Einsatz einer
doublenden Typ T programmieren wollen. Es handelt sich zudem Bibliothek zur Erzeugung von Test Doubles naheliegend.
um höchst spezialisierten Code, der ein tiefes Verständnis von Studentischer Code und Test Doubles gehören verschiedenen
Java Reflection und Generics erfordert. Schutzbereichen an. Test Doubles sind im Aufrufbaum Kinder des
Die naheliegende Idee ist nun, die Erzeugung der Proxy-Objekte studentischen Codes, so dass tendenziell restriktive Rechte des
in eine Bibliothek auszulagern, die dem AssignmentGrader- studentischen Codes an Test Doubles vererbt werden. Mock-
Schutzbereich angehört. Wir stellen im folgenden Abschnitt kurz Bibliotheken benötigen für ihre Test Doubles jedoch Rechte von
die Entwurfsideen einer neuen Bibliothek MockitoWrap als Hülle erheblichem Bedrohungspotential. Um den von der Lehrkraft
um mockito vor, die sich um die Erzeugung von Proxy-Objekten geschriebenen Bewertungscode nicht mit sicherheitsspezifischen
kümmert, welche Aufrufe an Test Doubles delegiert, wobei jeder Details (Proxy-Objekte mit in doPrivileged-Aufrufen gekapselten
delegierte Aufruf in ein doPrivileged-Konstrukt „verpackt“ ist. Delegationen) zu „verschmutzen“, bietet sich die Verlagerung
dieser Details in die Mock-Bibliothek oder in einen hierfür zu
4.3 Zentrale Entwurfsideen von Mockito- schreibenden Adapter an. Die Erstellung eines solchen Adapters
Wrap kann durch Nutzung von Java Generics und der Java-Reflection-
Die zentrale Operation (vgl. Abschnitt 2.4) bei der Nutzung von Bibliothek kompakt gelingen.
mockito ist die generische Methode Mockito.mock(Class c)14.
Sie liefert ein Test Double vom Basistyp T, für das alle Methoden
6. Literaturverzeichnis
[Ed03] Edwards, S.: Using Test-Driven Development in the
der Klasse T aufrufbar sind. Das Test Double wird im weiteren
Classroom: Providing Students with Automatic,
Verlauf von Methoden wie Mockito.when oder Mockito.verify
Concrete Feedback on Performance. In Proc. Int’l Conf.
verwendet. An dieser Art des Aufrufs von mockito soll sich durch
Education and Information Systems: Technologies and
die beschriebene Sicherheitsanforderung nichts ändern. Einzig der
Applications (EISTA ’03), Aug. 2003.
Name der Einstiegsklasse Mockito soll nun MockitoWrap heißen.
[Go13] Gong, L.: JavaTM SE Platform Security Architecture.
Die vollständige Beschreibung von MockitoWrap würde den
http://docs.oracle.com/javase/7/docs/technotes/guides/
Rahmen dieses Aufsatzes sprengen. Wir nennen nur einige
security/spec/security-spec.doc.html, Abruf 13.09.2013.
grundlegende Entwurfsideen, die vermutlich in ähnlicher Form
auf andere Mock-Frameworks übertragen werden können. [Ka13] Kaczanowski, T.: Practical Unit Testing with JUnit and
MockitoWrap wird im Zuge der Erstellung neuer Programmier- Mockito. Verlag Tomasz Kaczanowski, 2013.
aufgaben sukzessive an der Hochschule Hannover weiter [KSZ02] Krinke J, Störzer M, Zeller A, Web-basierte
entwickelt. Programmierpraktika mit Praktomat, Softwaretechnik-
Entwurfsidee 1: Sei Class c der Typ, für den ein Test Double Trends, Vol. 22, (3), October 2002.
erstellt werden soll. Statt direkt Mockito.mock(c) aufzurufen, soll [Me07] Meszaros, G.: xUnit Test Patterns: Refactoring Test
der Wrapper genutzt werden: MockitoWrap.mock(c). Der Wrapper Code. Addison-Wesley Longman, Amsterdam, 2007.
delegiert den Aufruf an das Original (T td=Mockito.mock(c)) und
erstellt dann ein Proxy-Objekt für das Test Double td. Das Proxy- [oV13] o. V.: OWASP Risk Rating Methodology. https://www.
Objekt erhält als Konstruktorparameter ein Objekt einer neuen owasp.org/index.php?title=OWASP_Risk_Rating_Meth
generischen Klasse MockProxyInvocationHandler, die von odology&oldid=158022, Abruf 13.09.2013.
15
InvocationHandler erbt. MockProxyInvocationHandler besitzt [SBG10] Striewe, M.; Balz, M.; Goedicke, M.: Enabling Graph
als Instanzattribute Referenzen auf das Test Double td und dessen Transformations on Program Code, In Proceedings of
Klasse c16, so dass stets vom Proxy-Objekt zum Test Double the Fourth International Workshop on Graph-Based
navigiert werden kann. Tools (GraBaTs 2010), Enschede, Netherlands, 2010.
Entwurfsidee 2: Die Methode MockProxyInvocationHandler. [SL05] Spillner, A.; Linz, T.: Basiswissen Softwaretest (3.
invoke delegiert den Methodenaufruf innerhalb einer Privileged Auflage). dpunkt, Heidelberg, Germany, 2005
17
Action an das Test Double td. [St13] Stöcker, A., Becker, S., Garmann, R., Heine, F., Kleiner,
Entwurfsidee 3: Für weitere Klassen der mockito-Bibliothek wer- C., Bott, O. J.: Evaluation automatisierter Programm-
den nun (einfachere) Wrapper geschrieben werden. Bspw. besitzt bewertung bei der Vermittlung der Sprachen Java und
OngoingStubbingWrap ein Instanzattribut vom Originaltyp SQL mit den Gradern „aSQLg“ und „Graja“ aus
OngoingStubbing. Methodenaufrufe wie thenReturn werden an studentischer Perspektive. In Proceedings DeLFI, 2013.
das Instanzattribut delegiert. Rückgabewerte werden wieder in [TE08] Thornton, M., Edwards, S. H., Tan, R. P., Pérez-
Objekte der …Wrap-Klasse eingehüllt. Quiñones, M. A.: Supporting student-written tests of
GUI programs. In Proceedings of the 39th SIGCSE
14
http://docs.mockito.googlecode.com/hg/latest/index.html?org/ Technical Symposium on Computer Science Education.
mockito/Mockito.html ACM Press, New York, NY, 2008, pp. 537-541.
15
http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Invo
cationHandler.html
16
Type erasure bei Java Generics macht den Einsatz dieses
zweitgenannten Instanzattributs notwendig.
17
http://docs.oracle.com/javase/7/docs/api/java/security/Privi
legedAction.html