- Lexon.at

Werbung
Secure .NET Development
Autor: Martin Schagerl
Letzte Änderung am 10.07.2014
Version 1.1
Lexon e.U., Inh. Martin Schagerl, Holzing 52, A – 3254 Bergland
T: +43 / 676 / 7119622, E: [email protected], I: http://www.lexon.at
Secure .NET Development
Kurzfassung
In dieser Arbeit werden Schwachstellen sowie Fehler aufgezeigt, welche beim Entwickeln von .NET
Anwendungen entstehen können. Um die Sicherheit von Applikationen zu erhöhen, werden entsprechende
Gegenmaßnahmen und Lösungen erarbeitet, welche sowohl theoretisch also auch praktisch vorgestellt
werden. Software Entwickler können die Ergebnisse für bestehende und für neue Projekte nutzen. Das
.NET Framework bietet grundsätzlich sehr viel Sicherheitsfeatures an, jedoch müssen diese richtig
implementiert und benutzt werden. Dadurch kann die Qualität einer Software gesteigert werden, wodurch
spätere Schäden verhindert werden können.
Typische Schwachstellen in Webapplikationen wie Cross-Site Scripting, SQL Injection oder Direct Object
References werden analysiert und durch .NET Features behoben. Auch für die Verwendung von WCF oder
ASP.NET Webservices werden Sicherheitsmechanismen präsentiert. Da das .NET Framework sehr gut in
das Betriebssystem integriert ist, wird gezeigt, wie auf den Zertifikatsspeicher zugegriffen wird und dies für
kryptografische Verfahren genutzt werden kann. Dazu werden sowohl symmetrische als auch
asymmetrische Algorithmen behandelt, um den Schutz von sensiblen Daten zu gewährleisten. Zusätzlich
wird das Thema Reverse Engineering aufgegriffen, damit Programmroutinen und hartcodierte
Informationen nicht aufgedeckt werden können. Aber auch Techniken zum Schützen von
Konfigurationsdaten wie beispielsweise dem ConnectionString werden besprochen.
Die Ergebnisse dieser Arbeit bieten einen guten Leitfaden zum sicheren Entwickeln und Bereitstellen von
.NET Anwendungen.
Abstract
This paper describes vulnerabilities and errors, which may occur in developing .NET applications. To
increase the security level of applications, techniques and solutions for preventing security leaks in software
products are presented. For better understanding, the theoretical aspects will be explained with the help of
additional examples. Software developers may use the results for existing and new .NET projects. Basically
the .NET framework offers a lot of security features, but they must be implemented and used in a correct
way. With the use of these features the quality of software can be increased and subsequent damages
prevented.
Typical vulnerabilities of web applications such as cross-site scripting, SQL injection or direct object
references will be analyzed and resolved with the help of built-in .NET features. The thesis also presents
mechanisms for WCF and ASP.NET web services. Due to the fact that the .NET framework is well
integrated into the operating system, this paper shows a way to use the Windows certificate store for
cryptographic tasks. To ensure the protection of sensitive data, symmetric and asymmetric algorithms will
be explained and implemented. Additionally the topic "reverse engineering" is picked up. By following the
result presented, uncovering of program routines and hardcoded information can be avoided. Additionally
there will be a discussion on techniques for protecting configuration data, such as connection strings.
All in all this thesis provides a best practice guide for developing and deploying secure .NET applications.
2
Secure .NET Development
Inhaltsverzeichnis
1.
EINLEITUNG...................................................................................................................................... 6
1.1.
1.2.
1.3.
MOTIVATION UND RELEVANZ ................................................................................................................. 6
ZIELSETZUNG ....................................................................................................................................... 6
AUFBAU DER ARBEIT............................................................................................................................. 7
2.
FACHLICHES UMFELD VON .NET .................................................................................................. 8
2.1.
2.2.
2.3.
.NET ARCHITEKTUR ............................................................................................................................. 8
ENTITY FRAMEWORK .......................................................................................................................... 10
LINQ ................................................................................................................................................. 11
3.
WEB SECURITY .............................................................................................................................. 13
3.1.
3.1.1.
3.1.2.
3.1.3.
3.2.
3.2.1.
3.2.2.
3.2.3.
3.3.
3.4.
3.5.
3.6.
CROSS SITE SCRIPTING (XSS)........................................................................................................... 13
Reflected XSS .............................................................................................................................. 13
Stored XSS ................................................................................................................................... 15
DOM based XSS .......................................................................................................................... 17
SQL INJECTION .................................................................................................................................. 17
Unsichere Datenbankzugriffe ....................................................................................................... 17
Sichere Datenbankzugriffe ........................................................................................................... 19
Informationen einer Datenbank ermitteln ..................................................................................... 20
DIRECT OBJECT REFERENCE .............................................................................................................. 23
CROSS-SITE-REQUEST-FORGERY (CSRF) .......................................................................................... 25
AUTHENTIFIZIERUNG ........................................................................................................................... 28
ASP.NET W EB API ........................................................................................................................... 32
4.
WINDOWS COMMUNICATION FOUNDATION (WCF) .................................................................. 34
4.1.
4.2.
4.3.
ENDPOINTS ........................................................................................................................................ 34
SICHERHEITSMECHANISMEN ................................................................................................................ 37
WCF VS. ASP.NET W EB API............................................................................................................. 39
5.
KRYPTOGRAPHIE .......................................................................................................................... 40
5.1. SYMMETRISCHE VERFAHREN............................................................................................................... 40
5.1.1.
Diffie-Helman Protokoll ................................................................................................................. 44
5.2. ASYMMETRISCHE VERFAHREN............................................................................................................. 46
5.2.1.
Verschlüsselung ........................................................................................................................... 46
5.2.2.
Digital Signieren............................................................................................................................ 48
5.3. DIGITALE ZERTIFIKATE ........................................................................................................................ 50
5.3.1.
Verschlüsseln ............................................................................................................................... 51
5.3.2.
Digital Signieren............................................................................................................................ 53
6.
REVERSE ENGINEERING .............................................................................................................. 56
6.1.
GEGENMAßNAHMEN ............................................................................................................................ 58
7.
DEPLOYMENT ................................................................................................................................ 60
7.1. KONFIGURATIONSDATEN ..................................................................................................................... 60
7.1.1.
Clientanwendungen ...................................................................................................................... 60
3
Secure .NET Development
7.1.2.
Webanwendungen ........................................................................................................................ 60
7.2. STRONG NAMES ................................................................................................................................. 61
7.3. CLICKONCE-BEREITSTELLUNG ............................................................................................................ 63
8.
KONZEPTIONIERUNG EINES SECURE CODING DEMONSTRATORS ...................................... 65
8.1.
8.2.
8.3.
W EB SECURITY .................................................................................................................................. 65
KRYPTOGRAPHIE ................................................................................................................................ 66
WCF ................................................................................................................................................. 67
9.
ZUSAMMENFASSUNG & AUSBLICK............................................................................................ 68
9.1.
W EITERE FEHLERQUELLEN ................................................................................................................. 68
Abbildungsverzeichnis
Abbildung 1: .NET Architektur ....................................................................................................................... 9
Abbildung 2: Aufbau von Entity Framework [13] ......................................................................................... 11
Abbildung 3: Webseite für Reflected XSS Angriff ....................................................................................... 14
Abbildung 4: Ergebnis eines Relected XSS Angriffs .................................................................................. 14
Abbildung 5: Eingabe für eine Stored XSS Attacke .................................................................................... 16
Abbildung 6: Ausführung eines Stored XSS Code ..................................................................................... 16
Abbildung 7: Nicht ausgeführte SQL Injection ............................................................................................ 18
Abbildung 8: Ausgeführte SQL Injection ..................................................................................................... 19
Abbildung 9: Blind SQL Injection - Datenbanknamen ermitteln .................................................................. 23
Abbildung 10: CSRF anfällige Webapplikation ........................................................................................... 25
Abbildung 11: Inhalt der CSRF präparierten Webseite ............................................................................... 27
Abbildung 12: Cookie durch die AntiForgeryToken() Funktion ................................................................... 28
Abbildung 13: WCF Kommunikation im Klartext ......................................................................................... 38
Abbildung 14: Schlüsselaustausch abhören ............................................................................................... 44
Abbildung 15: Benutzerzertifikatsspeicher .................................................................................................. 51
Abbildung 16: E-Mail Signatur überprüfen .................................................................................................. 54
Abbildung 17: Dekompilierte Applikation .................................................................................................... 57
Abbildung 18: Originaler Source Code ....................................................................................................... 57
Abbildung 19: Reverse Engineering nach Obfuscating .............................................................................. 59
Abbildung 20: Signieren einer .NET Bibliothek ........................................................................................... 62
Abbildung 21: Information einer Assembly setzen ...................................................................................... 63
Abbildung 22: Exception bei manipulierten Bibliotheken ............................................................................ 63
Abbildung 23: Applikation mittels ClickOnce bereitstellen .......................................................................... 64
Abbildung 24: Herkömmlicher Ablauf des Web Security Demonstrators ................................................... 66
Abbildung 25: Angriffsvektoren des Web Security Demonstrators ............................................................. 66
Listings
Listing 1: Herkömmliche SQL Abfrage ........................................................................................................ 11
4
Secure .NET Development
Listing 2: LINQ Abfrage ............................................................................................................................... 12
Listing 3: Verhindern von gefährlichen Ausgaben in der View ................................................................... 15
Listing 4: Verhindern von gefährlichen Eingaben am Controller................................................................. 15
Listing 5: Unsicherer Datenbankzugriff ....................................................................................................... 18
Listing 6: Entity Framework - LINQ Abfrage ............................................................................................... 20
Listing 7: Nicht parametrisierte SQL Anweisung ........................................................................................ 20
Listing 8: Parametrisierte SQL Anweisung ................................................................................................. 20
Listing 9: Benutzerdefinierte Fehlermeldungen .......................................................................................... 21
Listing 10: Blind SQL Injection – Anzahl der Spalten ermitteln................................................................... 22
Listing 11: Berechtigung für Direct Object Reference überprüfen .............................................................. 24
Listing 12:HTML Code der CSRF anfälligen Webseite ............................................................................... 26
Listing 13: CSRF präparierte Webseite ...................................................................................................... 26
Listing 14: Implementieren der AntiForgeryToken() Funktion..................................................................... 27
Listing 15: HTML Code durch die AntiForgeryToken() Funktion ................................................................ 27
Listing 16: Attribut zum Überprüfen des CSRF Token ................................................................................ 28
Listing 17: Authorize Attribut ....................................................................................................................... 31
Listing 18: Implementierung der Forms Authentication .............................................................................. 31
Listing 19: OData - Anzahl der Datensätze einschränken .......................................................................... 33
Listing 20: OData - Operationen einschränken ........................................................................................... 33
Listing 21: Service Contract ........................................................................................................................ 35
Listing 22: WCF Endpoint (Service) ............................................................................................................ 36
Listing 23: WCF Endpoint (Client) ............................................................................................................... 36
Listing 24: WCF mit Transportsicherheit ..................................................................................................... 38
Listing 25: TCP Server für AES Kommunikation ........................................................................................ 41
Listing 26: TCP Client für AES Kommunikation .......................................................................................... 43
Listing 27: Diffie-Hellman Implementierung (Client) ................................................................................... 45
Listing 28: Diffie-Hellman Implementierung (Server) .................................................................................. 45
Listing 29: RSA Verschlüsselung (Server) .................................................................................................. 47
Listing 30: RSA Verschlüsselung (Client) ................................................................................................... 47
Listing 31: RSA Signatur erstellen .............................................................................................................. 48
Listing 32: RSA Signatur überprüfen .......................................................................................................... 49
Listing 33: Verschlüsseln mit Zertifikaten.................................................................................................... 52
Listing 34: Entschlüsseln mit Zertifikaten .................................................................................................... 53
Listing 35: Signatur mit einen Zertifikat erstellen ........................................................................................ 54
Listing 36: Signatur überprüfen ................................................................................................................... 55
Listing 37: Demonstrator: Start des gewünschten Verschlüsselungsalgorithmus ...................................... 67
Tabellenverzeichnis
Tabelle 1: Ablauf einer Forms Authentication [27] ...................................................................................... 30
Tabelle 2: Technologien von WCF [33, p. 7] .............................................................................................. 34
Tabelle 3: WCF Webservice vs. ASP.NET Web API [37] ........................................................................... 39
Tabelle 4: Funktionalitäten der Demo Webapplikation ............................................................................... 65
5
Secure .NET Development
1. Einleitung
1.1.
Motivation und Relevanz
Heutzutage steht es sicherlich außer Frage, dass eine sichere Software von enormer Bedeutung ist.
Dennoch gibt es zahlreiche Sicherheitslücken in bestehenden sowie neuentwickelten Softwareprodukten.
Ein Grund dafür ist, dass die Entwicklung von sicherer Software mit Zeitaufwand und somit mit Kosten
verbunden ist. Da Kunden meist nur die korrekte Funktionalität und eventuell das Aussehen einer
Anwendung bewerten, werden Sicherheitsaspekte von Entwicklern häufig ignoriert. Diese
Kosteneinsparungen können je nach Größe und Art der Software einen enormen finanziellen Schaden
bedeuten. Um ein paar Zahlen zu nennen: Laut einer Studie mit 150 Organisationen, kostet alleine die
Sanierung einer einzelnen Schwachstelle durchschnittlich 300.000 $. [1] Im Jahr 2007 hat schlecht
entwickelte Software einen Schaden von 180 Milliarden Dollar in der USA angerichtet. [2] Neben diesen
hohen Kosten können Sicherheitslücken das Image eines Unternehmens zerstören, wenn beispielsweise
persönliche Daten bzw. Kreditkarteninformationen von Angreifern aufgedeckt werden.
Viele Unternehmen, Institute, Organisationen und öffentliche Einrichtungen investieren viel Geld in ihre ITInfrastruktur, ohne Rücksicht auf Softwaresicherheit zu nehmen. Ohne Frage haben Systeme wie
beispielsweise Firewalls ihre Berechtigung und können bestimmte Angriffe abwehren, jedoch sind diese
vollkommen nutzlos, wenn eine Softwareschwachstelle aktiv ausnutzbar ist. Eine gute Sicherheitspolitik ist
gegeben, wenn in allen IT-Bereichen (Infrastruktur, Software, Clients, usw.) ein hohes Sicherheitsniveau
erreicht wird.
Um eine sichere Software zu entwickeln, empfiehlt es sich, auf bestehende Frameworks zurückzugreifen,
welche bewährte Sicherheitskonzepte anbieten. Solche Frameworks machen Anwendungen nicht nur
sicherer, sondern beschleunigen zusätzlich ihre Entwicklung. Es kann nämlich auf viele Funktionalitäten
zurückgegriffen werden, ohne diese neu entwickeln zu müssen. Microsoft, einer der größten
Softwarehersteller der Welt, stellt dazu das .NET Framework für Entwickler/innen zur Verfügung. [3, p. 11]
Einer der großen Vorteile dieses Frameworks ist, dass es in unterschiedlichen Anwendungstypen
verwendet werden kann:
 Konsolenanwendungen
 Desktopanwendungen
 Webanwendungen
 Webservices
Dadurch können Entwickler einerseits mit einem Know-How viele unterschiedliche Anwendungen erstellen,
und andererseits kann ein Code in mehreren Applikationen wiederverwendet werden.
1.2.
Zielsetzung
Im Vergleich zu klassischen Programmiersprachen wie C oder C++ bietet das .NET Framework viel
Unterstützung bei der Entwicklung sicherer Applikationen. Trotzdem beinhalten .NET Applikationen
Sicherheitsschwachstellen, verursacht z.B. durch
6
Secure .NET Development
 Verwendung unsicherer Aufrufe (z.B. Ausgabe ohne Codierung)
 unsichere Verwendung von Funktionen
 Fehler in der Logik (z.B. Integer Overflows)
 Aufrufe von Legacycode
 fehlerhafte Verwendung von Sicherheitsfunktionalität (z.B. Authentisierung, Autorisierung,
Verschlüsselung)
Das .NET Framework bietet jede Menge Sicherheitsfunktionalitäten an, welche jedoch nicht immer
automatisch zur Wirkung kommen, weil diese explizit von Programmierer/innen implementiert werden
müssen. Daher besteht trotz .NET die Möglichkeit, fatale Fehler zu machen, wodurch Sicherheitslücken
entstehen können. Aus diesem Grund ist es Aufgabe der Entwickler, die mitgelieferten Features richtig
einzusetzen, um Applikationen sicherer zu machen. In dieser Arbeit werden dazu typische Schwachstellen
von .NET Applikationen untersucht und diese mittels .NET Unterstützung behoben. Es wird gezeigt, was
bei den Sicherheitsfunktionen beachtet werden muss beziehungsweise welche Funktionen für welchen
Zweck geeignet sind.
Die konkrete Forschungsfrage dieser Arbeit lautet daher: Wie kann das .NET Framework sinnvoll genutzt
werden, um sichere, stabile und zukunftsorientierte Applikationen zu entwickeln?
1.3.
Aufbau der Arbeit
In Kapitel 2 wird ein fachlicher Einstieg geschaffen, damit die späteren Ansätze besser verstanden werden
können. Dabei wird ein Überblick über das Framework dargelegt und später verwendete Technologien
werden kurz angesprochen und erklärt.
Im Hauptteil wird veranschaulicht, wie das .NET Framework in den Bereichen Web Security, WCF,
Kryptographie und Deployment richtig eingesetzt werden sollte. Es werden häufige Entwicklungsfehler
aufgezeigt und dazu Best Practice Lösungen theoretisch sowie praktisch erläutert. Weiter wird im Hauptteil
der Punkt Reverse Engineering behandelt, um zu zeigen, wie einfach und gefährlich das Dekompilieren
von Anwendungen ist. Auch hierzu werden entsprechende Gegenmaßnahmen präsentiert. Damit
Anwendungen richtig bereitgestellt werden, wird ein kurzer Einblick in das Deployment von .NET
Applikationen gegeben.
Im letzten Kapitel werden die wichtigsten Punkte zusammengefasst und ein Ausblick gegeben.
7
Secure .NET Development
2. Fachliches Umfeld von .NET
Das .NET Framework ist eine von Microsoft entwickelte Laufzeitumgebung, welche eine Sammlung von
Klassenbibliotheken und Programmschnittstellen enthält. Das Framework ist im vollen Umfang nur für
Windows verfügbar, jedoch gibt es Open-Source-Projekte wie Mono, welche es erlauben, .NET
Applikationen auch auf anderen Plattformen wie Linux auszuführen. [4] [5]
In den folgenden Kapiteln werden der Aufbau des Frameworks sowie .NET Technologien näher erläutert,
um die späteren Ansätze besser verstehen zu können.
2.1.
.NET Architektur
 Programmiersprachen
Bevor eine .NET Anwendung entwickelt wird, muss entschieden werden, welche Programmiersprache
eingesetzt werden soll. Das Framework wurde von Beginn an dafür entwickelt, dass Entwickler in
unterschiedlichen Programmiersprachen arbeiten können. Es kann im Prinzip jede Sprache verwendet
werden, für die es einen Language Compiler gibt, welcher die Hochsprache in die Common Intermediate
Language (CIL) übersetzen kann. Eine Liste aller Sprachen findet man unter http://www.itvisions.de/dotnet/produkte/sprachen.aspx
Die Wahl der Programmiersprache ist abhängig von den vorhandenen Programmierkenntnissen sowie
dem Einsatzbereich der zu erstellenden Anwendung. Bei Bedarf ist es auch möglich, mehrere Sprachen
in einer Anwendung zu kombinieren. [6] Alle hier gezeigten praktischen Beispiele werden mit der
Programmiersprache C# demonstriert, da mittels dieser Sprache alle Vorteile von .NET Framework
vollständig genutzt werden können.
Das .NET Framework ermöglicht die Zusammenarbeit zwischen den unterschiedlichen Sprachen,
wodurch ein Programmcode aufgerufen werden kann, der in einer anderen .NET Sprache geschrieben
worden ist. Zusätzlich können Klassen vererbt werden, die in anderen Sprachen entwickelt worden sind.
Dieser Vorteil wird durch die Common Language Specification sowie dem Common Type System (CTS)
ermöglicht. [7] Das Common Type System definiert, wie Datentypen deklariert, verwendet und in der
Common Language Runtime verwaltet werden. Dies sorgt für eine Vereinheitlichung der Datentypen,
damit diese in allen benutzten Sprachen interoperabel sind. [8]
 Anwendungstypen
Wie bereits unter 1.1 angesprochen, können mit dem .NET Framework unterschiedliche
Anwendungstypen wie Desktop Anwendungen, Konsolen Anwendungen, Web Anwendungen, Web
Services und Windows Services entwickelt werden. Je nach ausgewähltem Anwendungstyp, werden
die jeweiligen Bibliotheken aus der Framework Class Library zur Verfügung gestellt.
 Framework Class Library (FCL)
Die Framework Class Library (FCL) ist eine Sammlung von Klassen und Datentypen, welche .NET
Anwendungen zum Lesen und Schreiben von Dateien, Zugreifen auf Datenbanken, Entwerfen von
grafischen Benutzeroberflächen, Konsumieren von Web-Services usw. nutzen können. Die FCL stellt
dabei viele Funktionen der Win32-API in einfachen. NET Objekten dar, die von den .NET
Programmiersprachen verwendet werden können. [9]
8
Secure .NET Development
 Common Intermediate Language (CIL)
Das .NET Framework arbeitet – genau wie die Programmiersprache Java - mit einer Zwischensprache.
Ein Compiler einer .NET Sprache erzeugt also keinen prozessorspezifischen Maschinencode, sondern
einen plattformunabhängigen Bytecode. Dieser Code wird Common Intermediate Language (CIL)
genannt – früher sprach man von der Microsoft Intermediate Language (MSIL). [10, pp. 1-2]
Erst zur Laufzeit wird der CIL-Code in einen Maschinencode (Native Code) umgewandelt. Der CIL-Code
wird dabei nicht wie bei Java interpretiert, sondern von einem sogenannten Just-in-Time-Compiler (JITCompiler) stückweise kompiliert und dann ausgeführt. Dabei berücksichtigt der JIT-Compiler
prozessorspezifische Optimierungsmöglichkeiten. Dadurch, dass nicht interpretiert, sondern vor der
Ausführung kompiliert wird und der JIT-Compiler sehr schnell arbeitet, ist der Performance-Verlust durch
die Intermediation sehr gering. [10, p. 2]
 Common Language Runtime
Die Ausführung einer .NET Anwendung setzt eine Laufzeitumgebung voraus, die sogenannte Common
Language Runtime (CLR). Die CLR stellt den JIT-Compiler und zahlreiche andere Dienste bereit, die
von allen .NET Programmiersprachen verwendet werden können. Dazu gehören zum Beispiel der
Garbage Collector, ein Exception Handling und ein Sicherheitssystem. [11]
Der Programmcode, der im Rahmen der CLR ausgeführt wird, heißt Managed Code (verwalteter Code).
Der restliche Code wird dann entsprechend Unmanaged Code (nicht-verwalteter Code) genannt.
Windows
Forms
Console
Framework
Class Library
Base
Class
Library
ADO.NET
Library
WPF,
WCF, …
Bytecode
Laufzeitumgeb
Ausführung
Language
Compiler
Anwendungst
Web
(MVC,
Service,
Common Intermediate Language
Common Language Runtime
Betriebssystem / Prozessor
Bytecode zu
Maschinecode
Sprach
C#, VBA, J#, F#, …
Common Language Specification
Common Type System
Abbildung 1: .NET Architektur
9
Secure .NET Development
2.2.
Entity Framework
Übliche Client-Server Applikationen sowie Webanwendungen sind häufig mit einer Datenbank verbunden.
Bekannte Datenbanksysteme wie Oracle, MySQL und Microsoft SQL verwalten ihre Daten in Form von
Tabellen und Spalten (Relationaler Speicher), während in modernen Programmiersprachen die
Datenverwaltung mittels Klassen (Objektorientierter Speicher) durchführen wird. [12, p. 887] Um diese
beiden unterschiedlichen Speicherformen zu verbinden, können sogenannte Object-Relational Mapping
(ORM) Frameworks wie das Entity Framework (EF) verwendet werden.
Eine weitere häufige Anforderung an Anwendungen ist, dass mehrere unterschiedliche Datenbanksysteme
unterstützt werden müssen. Wird beispielsweise eine Applikation für mehrere Unternehmen entwickelt, so
kann nicht davon ausgegangen werden, dass jedes Unternehmen dieselbe Datenbank im Einsatz hat. Um
mit mehreren Datenbanken kompatibel zu sein, müssen Datenbankzugriffe üblicherweise mehrfach
geschrieben werden, da SQL Statements zwischen den Systemen unterschiedlich sind. Dies würde nicht
nur einen hohen Aufwand bedeuten, sondern auch eine Menge an Nachteile wie Unübersichtlichkeit,
Wartungsintensivität und Fehleranfälligkeit mit sich bringen. Auch hier kann das Entity Framework Abhilfe
schaffen: Das Framework unterstützt Microsoft SQL Server, Oracle, MySQL und DB2. [12, p. 885]
Das EF wurde erstmalig 2008 in das .NET Framework 3.5 integriert und seither stark weiterentwickelt. Seit
dem .NET Framework 4 wird es über den Package Manager von Visual Studio NuGet ausgeliefert:
http://www.nuget.org/packages/EntityFramework
Das Entity Framework kann in zwei verschieden Ansätzen verwendet werden:
 Code First: Für Anwendungen, für die es noch keine Datenbank gibt. Hier werden zuerst die Klassen
geschrieben, welche dann mittels ORM mit der Datenbank verbunden werden.
 Database First: Für Anwendungen, die auf eine bestehende Datenbank zugreifen. Hier werden die
Tabellen und Spalten der bestehenden Datenbank in Klassen konvertiert und mittels ORM verbunden.
Alle hier gezeigten praktischen Beispiele werden mit dem Code First Ansatz durchgeführt.
In der Abbildung 2 wird die Architektur von Entity Framework gezeigt: In der obersten Schicht befindet sich
die Anwendung, wo die Abfragen in einer datenbankunabhängigen Sprache wie LINQ (siehe 2.3) formuliert
werden. Die erstellten Statements werden dann vom Entity Client entgegengenommen und auf das Entity
Daten Model angewendet. Wenn der Bedarf besteht, auf die Datenbank zuzugreifen, wird die Abfrage an
den jeweiligen ADO.NET Provider weitergegeben. Je nach Datenbanksystem wird hier ein anderer
Provider verwendet, welcher dann die nativen SQL Befehle zur Datenbank sendet. [12, pp. 880, 881]
10
Secure .NET Development
LINQ
Natives
SQL
Abbildung 2: Aufbau von Entity Framework [13]
2.3.
LINQ
Um Abfragen von der eingesetzten Datenquelle unabhängig zu machen, kann die sogenannten Language
Integrated Query (LINQ) eingesetzt werden. Hierbei handelt es sich um eine von Microsoft entwickelte
Abfragesprache, die den Zugriff auf Datenstrukturen vereinheitlicht. [14, p. 2] Dadurch macht es bei der
Entwicklung einer Anwendung keinen Unterschied, ob die Daten beispielsweise in einer Microsoft SQL
oder Oracle Datenbank gespeichert sind.
Im Unterschied zu herkömmlichen Datenbankabfragen, wo native SQL Anweisungen als String im Source
Code angegeben sind, werden LINQ Anweisungen in den Source Code eingebettet. Dadurch können
Fehler bereits beim Kompilieren und nicht erst zur Laufzeit festgestellt werden. [14, p. 14] So können Fehler
frühzeitig erkannt und behoben werden.
Beispiel einer Abfrage:
 Herkömmlich
1
SELECT * FROM Customers WHERE Country = 'Italy'
Listing 1: Herkömmliche SQL Abfrage
11
Secure .NET Development
 LINQ
1
2
3
from c in Customers
where c.Country == "Italy"
select c;
Listing 2: LINQ Abfrage
Wenn man den Code aus Listing 1 und Listing 2 vergleicht, fällt auf, dass bei LINQ eine Ähnlichkeit zur
SQL Sprache besteht. Dadurch fällt es leichter, die neue Abfragesprache zu erlernen.
12
Secure .NET Development
3. Web Security
Der Trend der letzten Jahre zeigt, dass Computer Applikationen häufig als Webapplikationen abgebildet
werden. Dadurch sind keine zusätzlichen Client-Installationen notwendig, die eingesetzte Anwendung ist
von überall erreichbar und Updates können zentral durchgeführt werden. Durch die hohe Verbreitung von
mobilen Geräten wie Smartphones und Tablets werden Webapplikationen weiter an Beliebtheit gewinnen,
da dadurch Anwendungen plattformunabhängig genutzt werden können.
In Gegensatz zu nativen Anwendungen können Webapplikationen in Kombination mit einem Cloud Dienst
bei hoher Auslastung automatisch auf mehrere Server skaliert werden, um alle Anfragen ohne Verzögerung
beantworten zu können. Dieser Vorgang wäre bei nativen Anwendungen nur mit sehr viel Aufwand möglich.
Da Webapplikationen bzw. Webservices in der Regel vom Internet zugänglich sind, haben
Sicherheitsmaßnahmen bei der Entwicklung höchste Priorität. Die hier erarbeiteten Sicherheitsaspekte
können sowohl für neue als auch für bestehende Webanwendungen übernommen werden.
Mit dem .NET Framework können sowohl Webanwendungen als auch Webservices erstellt werden. Bei
beiden Formen gibt es unterschiedliche Angriffspunkte, welche berücksichtigt werden müssen. Daher
werden in den nachfolgenden Unterkapiteln beide Formen behandelt.
3.1.
Cross Site Scripting (XSS)
Einer der häufigsten Angriffe auf Webapplikationen wird durch Cross Site Scripting (XSS) Attacken
durchgeführt. Diese Schwachstelle beruht auf einer fehlenden oder unzureichenden Überprüfung der Daten
vor der Ausgabe durch den Browser. Bei einem Angriff wird versucht, Script Code (z.B. JavaScript) an
einen Webserver zu senden, sodass der Schadcode beim nächsten Aufruf im Kontext des Opfers
ausgeführt wird. Im Gegensatz zu einer SQL Injection wird hier nicht die Datenbank der Webanwendung
angegriffen, sondern der Webserver bzw. der Client selbst. [15, p. 840] Dabei gibt es die drei nachfolgenden
XSS Möglichkeiten.
3.1.1. Reflected XSS
Hierbei handelt es sich um einen nicht-persistenten XSS Angriff, bei dem eine Benutzereingabe direkt vom
Server wieder zurückgeschickt wird. Da die Eingaben dabei nicht gespeichert werden, kann ein Code nur
einmal zur Ausführung kommen. [16]
Durch das nachfolgende Beispiel soll die Schwachstelle demonstriert werden:
 Auf einer Webseite gibt es eine Liste, welche durch einen Suchfilter eingeschränkt werden kann. Dabei
werden die eingegebenen Suchbegriffe zur Übersichtlichkeit wieder ausgegeben:
13
Secure .NET Development
Abbildung 3: Webseite für Reflected XSS Angriff
 Beim Klicken auf den „Filter“ Button werden im Query String die Suchparameter angegeben:
http://<domain>/Mile?searchEventName=XSS&searchEventType=
 Um nun eine Reflacted XSS Attacke durchzuführen, könnte man einen Skript Code in den Query String
einfügen und diese präparierte URL per E-Mail versenden:
http://<domain>/Mile?searchEventName=<script>alert(“Reflected XSS
Attacke“);</script>&searchEventType=
 Der Aufruf dieses Links würde zum folgenden Ergebnis führen
Abbildung 4: Ergebnis eines Relected XSS Angriffs
Damit diese Schwachstelle in .NET Webapplikationen verhindert wird, müssen folgende Aktionen
durchgeführt werden:
 View
Um einen Inhalt vom Server auszugeben,
@Html.Raw(ViewBag.SearchInput)
wird
häufig
folgende
Form
verwendet:
Durch das @Html.Raw (...) wird der übergebene Inhalt eins zu eins an den Browser
weitergegeben, wodurch ein Browser einen Script Code interpretieren würde. Um dies zu verhindern,
14
Secure .NET Development
muss der Inhalt kodiert werden, um
darstellbare HTML Tags zu ersetzen:
„<“  <
„>“  >
typische Zeichen eines Scripts, wie z.B „<“ oder „>“ durch
Dies kann durch folgenden Code erreicht werden:
1
<b>Results for:</b> @Html.Encode(ViewBag.SearchInput)
Listing 3: Verhindern von gefährlichen Ausgaben in der View
 Controller
Beim Controller darf auf keinen Fall das Methoden Attribut [ValidateInput(false)] gesetzt sein.
Wenn dieses Attribut nicht beziehungsweise auf True gesetzt ist, werden die übergebenen Parameter
auf Script Code überprüft. Sobald ein verdächtiger Inhalt übergeben wird, wird automatisch eine
Exception ausgelöst.
1
2
3
4
5
[ValidateInput(true)]
public ActionResult Index(string searchEventType, string searchEventName)
{
…
}
Listing 4: Verhindern von gefährlichen Eingaben am Controller
3.1.2. Stored XSS
Im Unterschied zur Reflected XSS wird bei der Stored XSS der Schadcode auf dem Webserver bzw. in der
Datenbank der Webapplikation gespeichert, wodurch er bei jeder Anfrage zurückgeliefert wird und zur
Ausführung kommen kann. [16] Da der Schadcode mehrmals zur Ausführung kommen kann, ist dieser
Angriff wesentlich gefährlicher als bei Reflected XSS.
Store XSS Attacken sind möglich, sobald eine Webapplikation Benutzerdaten entgegennimmt und ohne
Prüfung speichert und diese später wieder ausliefert.
Das nachfolgende Beispiel soll die Schwachstelle praktisch demonstrieren:
 Auf einer Webseite können Benutzereingaben an den Server gesendet werden. Hier wird in unserem
Fall ein einfacher JavaScript Code eingegeben und übermittelt.
15
Secure .NET Development
Abbildung 5: Eingabe für eine Stored XSS Attacke
 Sobald die neuen Daten abgefragt werden, kommt der JavaScript Code zur Ausführung
Abbildung 6: Ausführung eines Stored XSS Code
Natürlich würde ein geschickter Angreifer anstelle des Öffnens eines Popup eine andere Aktion
durchführen, wie beispielsweise die Cookies auslesen. Dadurch könnte ein Angreifer beispielsweise die
Session eines anderen Benutzers übernehmen.
Um diese Schwachstelle in .NET Webapplikationen zu verhindern, müssen dieselben Gegenmaßnahmen
wie bei den Reflected XSS durchgeführt werden (siehe 3.1.1). Weiters müssen sichere Methoden für den
Datenbankzugriff verwendet werden (siehe 3.2.2)
 View
Alle Ausgaben kodieren. Dadurch werden Script Tags in HTML Tags umgewandelt und werden somit
nicht ausgeführt, sondern dargestellt.
 Controller
Auf keinen Fall das Attribut [ValidateInput(false)]
weglassen oder den Parameter auf True setzen.
setzen, sondern entweder das Attribut
16
Secure .NET Development
3.1.3. DOM based XSS
Diese Attacke ist völlig unabhängig vom Webserver der Webseite. Daher können auch statische Webseiten
betroffen sein. Bei DOM based XSS wird der Schadcode direkt an den Client übergeben und dort zur
Ausführung gebracht, ohne eine Anfrage an den Webserver zu stellen. Dazu könnte beispielsweise der
Query String einer URL so verändert werden, dass ein Script Code im Kontext des Opfers ausgeführt wird.
[16]
Da es sich hierbei um eine Schwachstelle am Client handelt, gibt es von .NET keine Gegenmaßnahmen.
Um der Schwachstelle entgegen zu wirken, müssen alle am Client verarbeiteten Daten überprüft bzw.
kodiert werden.
3.2.
SQL Injection
Eine SQL Injection ist eine Attacke gegen Datenbank-basierte Applikationen. Erfolgreiche Angriffe können
es einem Angreifer ermöglichen, sich unerlaubt in eine Web-Applikation mit Zugriffsschutz einzuloggen,
private Informationen aus einer Datenbank zu entwenden oder Daten zu manipulieren. [17]
Der Angreifer versucht dabei, Benutzereingaben so zu formulieren, dass diese Eingaben die
Datenbankabfrage verändern, um eigene SQL Anweisungen an die Datenbank zu senden. Der Angriff wird
möglich, wenn Eingaben ohne Überprüfungen in die Abfragen übernommen werden.
3.2.1. Unsichere Datenbankzugriffe
Es gibt mehrere Möglichkeiten, um aus einer .NET Anwendung auf eine Datenbank zuzugreifen. Einige
sind jedoch bereits veraltet und sollten auf keinen Falls mehr benutzt werden.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// create and open SQL connection
var connection = new SqlConnection();
connection.ConnectionString =
ConfigurationManager.ConnectionStrings["ConnString"].ConnectionString;
connection.Open();
// generate select statement
string query = "SELECT m.Id, m.Name, m.Amount, m.IsAccepted, m.Comment,
e.Name, u.Username";
query += " FROM Miles m INNER JOIN EventTypes e on m.Type_Id = e.Id";
query += " INNER JOIN ApplicationUsers u on m.User_Id = u.Id";
List<string> whereStatements = new List<string>();
if (!IsAdmin)
whereStatements.Add("m.User_Id = " + <UserId> + "");
if (!string.IsNullOrEmpty(searchEventName))
whereStatements.Add("m.Name LIKE '%" + searchEventName + "%'");
17
Secure .NET Development
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
if (!string.IsNullOrEmpty(searchEventType))
whereStatements.Add("m.Type_Id = '" + searchEventType + "'");
for (int i = 0; i < whereStatements.Count; i++)
{
if (i == 0)
query += " WHERE ";
else
query += " AND ";
query += whereStatements[i];
}
// execute select statement
SqlCommand command = new SqlCommand(query, connection);
SqlDataReader reader = command.ExecuteReader();
// process data
// ...
Listing 5: Unsicherer Datenbankzugriff
Im Beispiel von Listing 5 werden folgende Aktionen durchgeführt:
 Zeile 3 – 6: Die Datenbankverbindung wird instanziiert und mit den Verbindungsdaten konfiguriert,
welche aus der web.config ausgelesen werden. Weiteres wird die Verbindung zum Datenbankserver
geöffnet.
 Zeile 9 - 12: Das Select Statement wird zusammengestellt.
 Zeile 14 – 32: Es wird überprüft, ob ein Filter angegeben wurde. Wenn ja, wird ein entsprechendes
Where Statement zur SQL Anweisung hinzugefügt.
 Zeile 35: Es wird ein SqlCommand Objekt angelegt und mit der Datenbankverbindung sowie dem Select
Statement initialisiert.
 Zeile 36: Das Select Statement wird zur Datenbank gesendet und ausgeführt. Die zurückgelieferten
Daten werden im SqlDataReader Objekt abgespeichert.
Der Code von Listing 5 kann folgendermaßen angegriffen werden:
 Sobald die Seite aufgerufen wird, welche die SQL Anweisung von Listing 5 ausführt, werden nur die
eigenen Einträge angezeigt.
Abbildung 7: Nicht ausgeführte SQL Injection
18
Secure .NET Development
 Nun kann ein Suchbegriff so formuliert werden, dass damit die SQL Anweisung manipuliert wird und
alle Einträge ausgibt. Es könnte beispielsweise nach irgendetwas' or 1=1 -– gesucht werden.
Dadurch würde die Variable „query“ von Listing 5 folgenden Inhalt bekommen:
SELECT m.Id, m.Name, m.Amount, m.IsAccepted, m.Comment, e.Name, u.Username
FROM Miles m INNER JOIN EventTypes e on m.Type_Id = e.Id INNER JOIN
ApplicationUsers u on m.User_Id = u.Id WHERE m.User_Id = 2 AND m.Name LIKE
'%irgendetwas' or 1=1--%'
Da die Zeichen „%‘" am Ende mittels „--" auskommentiert werden, werden diese nicht vom SQL Server
ausgeführt, wodurch es zu keinem Syntaxfehler kommt. Daher steht am Schluss der Anweisung 1=1,
was immer True liefert und somit auf jede Zeile zutrifft.
Abbildung 8: Ausgeführte SQL Injection
Damit ein solcher Angriff verhindert werden kann, muss der Zugriff auf die Datenbank geändert werden.
Dazu gibt es zwei Möglichkeiten, welche im nächsten Kapitel erklärt werden.
3.2.2. Sichere Datenbankzugriffe
Um in .NET Anwendungen mit einer Datenbank zu kommunizieren, wird seitens Microsoft das Entity
Framework empfohlen. [18] Wie unter 2.2 beschrieben bietet dieses ORM Framework nicht nur
sicherheitsrelevante Vorteile, sondern beschleunigt und erleichtert zusätzlich die Entwicklung. Um den
unsicheren Datenbankzugriff aus Listing 5 nun mit dem Entity Framework durchzuführen, muss folgender
Code geschrieben werden:
1
2
3
4
5
6
7
8
9
10
ApplicationDbContext context = new ApplicationDbContext();
IQueryable<Mile> miles = context.Mile.AsQueryable();
if (!string.IsNullOrEmpty(searchEventName))
miles = miles.Where(m => m.Name.Contains(searchEventName));
if (!string.IsNullOrEmpty(searchEventType))
miles = miles.Where(m => m.Type.Id.Equals(searchEventType));
if (!IsAdmin)
miles = miles.Where(m => m.User.Id.Equals(<UserId>));
return View(miles.ToList());
19
Secure .NET Development
Listing 6: Entity Framework - LINQ Abfrage
Im Beispiel von Listing 6 werden folgende Aktionen durchgeführt:
 Zeile 1: Es wird eine Instanz von der Klasse ApplicationDbContext erzeugt. Diese Klasse ist von
DBContext abgeleitet und verfügt über Informationen, wie die Datenbankverbindung, Metadaten des
Datenmodels sowie eine Änderungsverfolgung.
 Zeile 2: Es wird ein Queryable Object mit dem Type Mile erzeugt. Mithilfe dieses Objekts können
LINQ Abfragen erstellt werden. Hier werden noch keine Daten von der Datenbank abgefragt.
 Zeile 3 – 8: Es wird überprüft, ob ein Filter gesetzt wurde. Wenn ja, wird ein entsprechendes LINQ
Statement angegeben. Auch hier werden noch keine Daten von der Datenbank abgefragt.
 Zeile 10: Erst durch die Methode ToList() wird die SQL Anweisung ausgeführt und die Ergebnisse
werden zurückgeliefert.
Wenn man mit älteren .NET Frameworks (< 3.5 SP1) arbeitet, kann das Entity Framework nicht genutzt
werden. [19] Jedoch gibt es auch eine andere Technik zum Verhindern von SQL Injections: Anstatt die
Benutzereingaben direkt in die Anweisung einzufügen, kann die Klasse SqlParameter verwendet
werden. Dabei werden in der SQL Anweisung Variablen definiert, welche zu einem späteren Zeitpunkt
durch die entsprechenden Werte (Benutzereingaben) ersetzt werden. [20]
 Nicht parametrisiert
1
2
queryString = "SELECT * FROM Miles WHERE User_Id =‘" + userId + "‘ AND
Name LIKE ‘%" + name + "%‘"
Listing 7: Nicht parametrisierte SQL Anweisung
 Parametrisiert
1
2
3
4
queryString = "SELECT * FROM Miles WHERE Username=@ID AND Name LIKE
@NAME";
command.Parameters.AddWithValue("@ID", userId);
command.Parameters.AddWithValue("@NAME ", name);
Listing 8: Parametrisierte SQL Anweisung
In Listing 7 wird die SQL Anweisung mit einer Zeichenkettenoperation zusammengestellt, wodurch eine
SQL Injection möglich wird. Daher sollte die Anweisung mittels Parameter, wie in Listing 8 gezeigt, erstellt
werden. In den Zeilen 1 – 2 werden die beiden Variablen „ID“ und „Name“ gesetzt. In den Zeilen 3 – 4
werden diese dann durch die entsprechenden Werte ersetzt.
3.2.3. Informationen einer Datenbank ermitteln
Um komplexere SQL Injections durchführen zu können, muss das Schema der Zieldatenbank bekannt sein.
Das bedeutet, der Angreifer muss wissen, wie die Tabellen heißen, welche Spalten diese besitzen und wie
diese zusammenhängen (Relationen). Da dem Angreifer jedoch in den meisten Fällen das
20
Secure .NET Development
Datenbankschema nicht
herauszufinden:
bekannt ist, wird versucht, dieses mit den nachfolgenden Methoden
 Analysieren von Fehlermeldungen
Bei dieser Methode werden fehlerhafte SQL Anweisungen generiert, um aussagekräftige
Fehlermeldungen zu produzieren. Anhand solcher Fehlermeldungen können Tabellennamen,
Spaltennamen oder Datentypen entnommen werden. Um dies bei .NET Webapplikationen zu
verhindern, sollte immer folgender Eintrag in der web.config vorgenommen werden:
1
2
3
4
5
6
7
8
9
10
<configuration>
<system.web>
<customErrors defaultRedirect="MyErrorPage.htm"
mode="RemoteOnly">
<error statusCode="500"
redirect="InternalError.htm"/>
</customErrors>
</system.web>
</configuration>
Listing 9: Benutzerdefinierte Fehlermeldungen
Dadurch wird bei einem Fehler eine benutzerdefinierte Fehlermeldung ausgegeben. Diese sollte keine
technischen Informationen enthalten, sondern nur darüber informieren, dass ein Fehler aufgetreten ist. Im
Listing 9 wird in der Zeile 3 die Webseite angegeben, welche diese Fehlermeldung enthält. In der Zeile 4
wir angegeben, dass benutzerdefinierte Fehlermeldungen nur für Remoteclients ausgegeben werden. So
werden ASP.NET-Fehlermeldungen weiterhin für den lokalen Host angezeigt, wodurch Administratoren
oder Entwickler die detaillierten Fehlermeldungen erhalten. Wie man in den Zeile 6 – 7 sehen kann, können
für bestimmte Fehlertypen unterschiedliche Fehlerseiten verwendet werden.
 Blind SQL
Wenn Webapplikationen entweder keine detaillierten Fehlermeldungen liefern, beziehungsweise bei
Fehlern gar keine Daten ausgeben (z.B. eine leere Liste), dann können Informationen mithilfe von Blind
SQL Injections ermittelt werden. Bei dieser Methode werden systematisch unterschiedliche Kombinationen
von Anweisungen ausprobiert und danach die Antworten ausgewertet. [21]
Wie in der Abbildung 8 zu sehen ist, konnte eine SQL Injection bereits erfolgreich durchgeführt werden.
Doch wir haben noch keine Informationen über die Datenbank selbst erhalten. Wenn wir zum Beispiel
wissen möchten, wie viele Spalten beim Filtern der Liste aus Abbildung 8 abgefragt werden, müssten wir
zunächst folgende Anfragen generieren:
21
Secure .NET Development
Listing 10: Blind SQL Injection – Anzahl der Spalten ermitteln
Da die Daten ohne einer Fehlermeldung ausgegeben werden, wissen wir, dass die SQL Anweisung
erfolgreich durchgeführt worden ist. Daher fahren wir mit folgenden Anweisungen fort:
xyz'
xyz'
xyz'
xyz'
xyz'
xyz'
xyz'
order
order
order
order
order
order
order
by
by
by
by
by
by
by
2
3
4
5
6
7
8
--------
// Kein Fehler
// Kein Fehler
// Kein Fehler
// Kein Fehler
// Kein Fehler
// Kein Fehler
// Fehler
Wir wissen jetzt, dass die Abfrage aus sieben Spalten besteht. Diese Information benötigen wir für die
nachfolgenden Schritte.
Auf einer MS SQL Datenbank kann der aktuelle Datenbankname mit folgender Anweisung abgefragt
werden:
SELECT DB_NAME()
Da wir nun wissen, wie viele Spalten die Abfrage hat und wie wir den aktuellen Namen der Datenbank
auslesen, probieren wir die folgende Anweisung:
xyz' union all SELECT DB_NAME(),null,null,null,null,null, null -Mit UNION vereinen wir die Ausgabe der ersten und zweiten Abfrage, wobei die zweite Abfrage den
Datenbanknamen ausgibt. Da die Anzahl der Spalten bei beiden Abfragen ident sein muss, werden die
restlichen sechs Spalten mit null befüllt. Der Befehl lieferte jedoch leider eine leere Ausgabe. Der Grund
dafür könnte sein, dass die erste Spalte nicht für die Ausgabe verwendet wird (es handelt sich
wahrscheinlich um eine ID). Aus diesem Grund geben wir den Datenbanknamen in der zweiten Spalte aus:
xyz' union all SELECT null, DB_NAME(),null,null,null,null, null --
22
Secure .NET Development
Abbildung 9: Blind SQL Injection - Datenbanknamen ermitteln
Wie in Abbildung 9 ersichtlich, konnte der Datenbankname erfolgreich ermittelt werden. Nun können eine
Reihe weitere Informationen abgefragt werden:
Alle Tabellennamen ermitteln:
xyz' union all SELECT null,name,null,null,null,null, null FROM
WebSecurity..sysobjects WHERE xtype = 'U' -Alle Spalten der Tabelle Miles ermitteln:
xyz' union all SELECT null,COLUMN_NAME,null,null,null,null, null FROM
information_schema.columns WHERE table_name = 'Miles' -Wie man sehen kann, hat man beinahe alle Möglichkeiten, um auf die Datenbank zuzugreifen. Es ist aber
auch möglich, Datensätze zu löschen oder zu verändern.
Alle Einträge aus der Tabelle Miles löschen:
xyz'; DELETE FROM Miles -Um alle diese Angriffe zu unterbinden, müssen die Datenbankzugriffe entweder parametrisiert oder mittels
Entity Framework durchgeführt werden. (siehe 3.2.2)
3.3.
Direct Object Reference
Bei Webanwendungen werden Referenzen/Verweise verwendet, um auf bestimmte Objekte zuzugreifen.
Dabei kann es sich um Dateien, Verzeichnisse oder Datenbankeinträge handeln. Bei einer Insecure Direct
Object Reference kann der Verweis auf diese Objekte vom Angreifer manipuliert werden, um so Zugriff auf
nicht berechtigte Inhalte zu bekommen.
Vor allem wenn Applikationen mit sensiblen Daten arbeiten, sind diese Attacken gefährlich. Konkret
verwenden Angreifer meist manipulierte IDs oder Pfadangaben, um etwa fremde Datensätze aus der
Datenbank auszulesen. [22]
23
Secure .NET Development
Das nachfolgende Beispiel soll die Schwachstelle demonstrieren:
 In einer Webapplikation kann ein angemeldeter Benutzer eine Übersicht über alle seine getätigten
Transaktionen abrufen. Dazu wird folgende URL aufgerufen:
http://<domain>/Account/TransactionList/3
 An der URL lässt sich feststellen, dass im Query String der Wert 3 übergeben wird. In ASP.NET kann
ein Default Parameter definiert werden, wodurch nur mehr der Wert angegeben werden muss. Wenn
zum Beispiel „id“ als Default Parameter definiert wurde, dann würden die zwei nachfolgende Aufrufe
zum selben Ziel führen:
http://<domain>/Account/TransactionList/3
http://<domain>/Account/TransactionList?id=3
 Um eine Insecure Direct Object Reference Attacke durchzuführen, muss lediglich ein anderer Wert
übergeben werden. Wenn man dadurch Zugriff auf den Inhalt eines anderen Benutzers bekommt, so
war der Angriff erfolgreich. Beispiel für Aufruf:
http://<domain>/Account/TransactionList?id=4
Damit diese Schwachstelle in .NET Webapplikationen verhindert wird, sind folgende Mechanismen
möglich:
 Eindeutig identifizierbare Objekte sollten immer mit einem Globally Unique Identifier (GUID) adressiert
werden. Dabei handelt es sich um eine 128 Bit lange Zeichenfolge, wodurch es 2128 (= 340 Sextillionen)
Möglichkeiten gibt. [23] Die Wahrscheinlichkeit für eine Kollision ist somit sehr gering.
GUIDs werden üblicherweise im Format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX dargestellt,
wobei jedes ‘X’ für einen hexadezimalen Wert (0-9 oder A-F) steht.
Dadurch würde der Aufruf folgendermaßen aussehen:
http://<domain>/Account/TransactionList?id= aa6cd0a0-fd0a-4fdd-8bb5dc155e1f3a59
 Zusätzlich sollte auf der Serverseite überprüft werden, ob der aktuelle Benutzer für die angefragte
Ressource berechtigt ist. Wenn der Zugriff nicht erlaubt ist, sollte der HTTP Code 403 (Forbidden)
zurückgeliefert werden.
Um beispielsweise in .NET sicherzustellen, dass eine Ressource nur für Benutzer mit der Admin Rolle
sowie für den eigenen Benutzer bereitgestellt wird, kann folgender Code angewendet werden:
1
2
3
if (!User.IsInRole(“admin“) && !User.Identity.GetUserId().Equals(id))
throw new HttpException((int)HttpStatusCode.Unauthorized,
„Forbidden");
Listing 11: Berechtigung für Direct Object Reference überprüfen
24
Secure .NET Development
Die Variable „id“ enthält die ID für die angeforderte Ressource. In diesem Beispiel (Listing 11) wird hier
die ID eines Benutzers angegeben.
3.4.
Cross-Site-Request-Forgery (CSRF)
Eine Cross-Site-Request-Forgery (CSRF) ist eine weitere Angriffsmöglichkeit auf eine Webapplikation, um
Aktionen im Kontext einer anderen Person (Opfer) durchzuführen. Dabei nutzt ein Angreifer die Session
seines Opfers zum Senden von manipulierten Anfragen (POST Requests) an den Webserver. Um eine
solche Attacke erfolgreich auszuführen, muss also ein angemeldeter Benutzer dazu gebracht werden, die
präparierten Request an den Server zu schicken. [24] Dazu stehen folgende Möglichkeiten offen:
 Cross-Site-Scripting: Wenn eine Webanwendung eine XSS Schwachstelle besitzt, kann der Angreifer
ein HTML oder einen JavaScript Code einschleusen, welcher die entsprechenden POST Requests
durchführt. Der Code würde bei einer späteren Anfrage im Kontext des aufgerufenen Benutzers
ausgeführt werden. Nähere Informationen zu XSS können unter 3.1 nachgelesen werden.
 URL: Ist eine Webapplikation nicht XSS anfällig, so können die manipulierten Requests auch über eine
eigene Webseite bereitgestellt werden. Die Webseite muss nicht einmal Teil der betroffenen
Webapplikation sein, sondern kann unter einer anderen Adresse bzw. Domain bereitgestellt werden.
Die URL der präparierten Seite wird üblicherweise per E-Mail oder über Sozial Media verteilt. Im
Gegensatz zu XSS muss der Angreifer hier das Opfer aktiv dazu bringen, die Webseite aufzurufen.
 Lokale Schadsoftware: Wenn es möglich ist, eine Schadsoftware auf dem Computersystem des Opfers
zu installieren, welches Zugriff auf den Browser hat, kann die Attacke auch durch den installierten
Schadcode durchgeführt werden. Dieser muss den Browser dazu bringen, die präparierte Webseite
aufzurufen.
Das nachfolgende Beispiel soll die Schwachstelle praktisch demonstrieren:
 Auf einer Webseite können angemeldete Benutzer ihre gesammelten Meilen (Punkte) an andere
Benutzer übertragen. Die Meilen werden dann vom eigenen Kontostand abgebucht und beim anderen
Benutzer gutgeschrieben.
Abbildung 10: CSRF anfällige Webapplikation
25
Secure .NET Development
 Um eine CSRF durchzuführen, muss ermittelt werden, welche Daten an den Webserver übertragen
werden. Dazu einfach den dazugehörigen HTML Code analysieren:
1
2
3
4
5
6
7
<form action="/Donation/Create" method="post">
<label>Amount</label>
<input id="Amount" name="Amount" type="text" value="0" />
...
</form>
Listing 12:HTML Code der CSRF anfälligen Webseite
Wie man in Listing 12 sehen kann, finden man im HTML Code alle notwendigen Informationen:
 an welche Adresse die Daten gesendet werden: <domain>/Donation/Create
 welche Daten übertragen werden: Alle input Tags innerhalb des form Tags
 Da nun alle notwendigen Informationen bekannt sind, kann eine eigene Webseite erstellt werden,
welche den POST Request schickt:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<html>
<head>
<title>Invitation</title>
</head>
<body style="background-color:#EDECEC">
<image src="invitation.jpg" width="150" height="100" /><br />
<form action="<domain>/Donation/Create" method="post">
<input type="hidden" id="Amount" name="Amount" value="200" />
<input type="hidden" id="Receiver" name="Receiver " value="user2" />
<input type="submit" value="Show details" />
</form>
</body>
</html>
Listing 13: CSRF präparierte Webseite
 Zeile 8: Es wird eine Einladung als Grafik angezeigt. Dem Opfer soll dadurch vermittelt werden, dass
er sich auf einer Webseite befindet, wo er Informationen zu einer Einladung findet.
 Zeile 10 – 14: Die Daten für die Anfrage werden angegeben. Die Input Tags die den Type hidden
besitzen, werden nicht angezeigt. So fällt dem Opfer nicht auf, dass Daten mit seiner Identität versendet
werden.
Auf der Webseite ist nun der nachfolgende Inhalt (siehe Abbildung 11) zu sehen. Beim Klick auf „Show
details“ werden die Daten an den Webserver geschickt, wodurch sich der Benutzer „user2“ 200 Meilen
vom aktuellen eingeloggten Benutzer überträgt.
26
Secure .NET Development
Abbildung 11: Inhalt der CSRF präparierten Webseite
Um dieser Schwachstelle Herr zu werden, muss im form Tag des POST Request ein Token angehängt
werden. Zusätzlich muss der idente Token auch in den Cookies abgespeichert werden. Sobald die Daten
an den Server gesendet werden, kann serverseitig überprüft werden, ob der Token im Formular und der
von den Cookies ident sind. Wenn ja, ist sichergestellt, dass die Daten nicht von einem Dritten geschickt
wurden. Um diesen Schutzmechanismus in einer .NET Webapplikation zu implementieren, sind die
folgenden Schritte notwendig: [25]
 View
Das Framework besitzt die Hilfsfunktion AntiForgeryToken(), welche am Client einen Token im
Formular sowie in den Cookies setzt. Die View muss dazu folgendermaßen erstellt werden:
1
2
3
4
5
6
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
...
}
Listing 14: Implementieren der AntiForgeryToken() Funktion
Durch diese Anweisung wird an den Client folgender HTML Code ausgeliefert:
1
2
3
4
<form action="/Donation/Create" method="post">
<input name="__RequestVerificationToken" type="hidden"
value="Jnr7YTsjVA11BrR3FOs5_fwiKKx3GsDongdLUfWDuwWJVvIz18nQ15_EBrsE35b79zNxF-NLFrcu16TYFd7ms5_GOQ-rVvXcFtu9-J--0Q1" />
Listing 15: HTML Code durch die AntiForgeryToken() Funktion
Zusätzlich wird folgender Token in den Cookies gesetzt:
27
Secure .NET Development
Abbildung 12: Cookie durch die AntiForgeryToken() Funktion
 Controller
Um nun serverseitig zu überprüfen, ob der Token im Formular und der in den Cookies gleich ist, muss
bei der entsprechenden Methode das Attribut [ValidateAntiForgeryToken] gesetzt werden. Der
Methodenkopf würde folgendermaßen aussehen:
1
2
3
4
5
6
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CreateDonateViewModel donatemile)
{
...
}
Listing 16: Attribut zum Überprüfen des CSRF Token
Mit den beiden Attributen aus Listing 16 wird sichergestellt, dass es sich um einen POST Request
handeln muss, bei welchem der Token im Formular und in den Cookies gleich ist. Sollte der Token nicht
gesetzt bzw. korrekt sein, so wird eine Exception mit der Nachricht „A required anti-forgery token was
not supplied or was invalid” ausgelöst.
3.5.
Authentifizierung
Mit dem .NET Framework gibt es verschiedene Möglichkeiten, um einen Authentifizierungsprozess
durchzuführen. Dabei kümmern sich die mitgelieferten Bibliotheken standardmäßig um viele
sicherheitsrelevante Angelegenheiten, wie zum Beispiel das Erstellen von sicheren Cookies am Client. [26]
Beim Entwickeln von .NET Anwendungen sollte man immer auf die zur Verfügung stehenden Bibliotheken
zurückgreifen und nicht selbst den Authentifizierungsprozess entwickeln, da es sich hierbei um einen sehr
kritischen Vorgang handelt. Es müssen eine Reihe an Sicherheitsaspekten erfüllt werden, um resistent
gegen Angriffe zu sein. Da die mitgelieferten Bibliotheken auch von vielen anderen Entwicklern eingesetzt
werden, sind diese weit verbreitet und haben sich dadurch bewährt.
In .NET Anwendungen stehen mehrere unterschiedliche Authentifizierungsmöglichkeiten zur Verfügung.
Abhängig vom Speicherort der Zugangsdaten muss die passende Form gewählt werden. Dabei werden
folgende Möglichkeiten angeboten: [26]
 Individual Accounts
Diese Authentifizierungsart muss gewählt werden, wenn die Zugangsinformationen in einer eigenen
Datenbank gespeichert werden. Ein Benutzer kann sowohl mittels Benutzername und Passwort
registriert werden als auch über eine Anmeldung an einem externen Anbieter wie Facebook, Google,
28
Secure .NET Development
Microsoft oder Twitter. Bei dieser Auswahl wird ASP.NET Identity (auch als
eingesetzt, welche alle notwendigen Methoden und Attribute bereitstellt.
ASP Membership)
 Organizational Accounts
Wenn die Benutzerdaten in Azure Active Directory oder Windows Server Active Directory gespeichert
sind, so muss die sogenannte Organizational Authentication gewählt werden. Dadurch können bereits
bestehende Benutzerdaten für den Zugriff auf eine Webapplikation verwendet werden.
 Windows Authentication
Diese Authentifizierungsform ist für eine Webapplikation im Intranet gedacht. Dabei wird ein SingleSign-On (SSO) vom lokal angemeldeten Windows Benutzer durchgeführt.
Da bei Webapplikationen am häufigsten die Individual Accounts verwendet werden, wird deren
Funktionalität hier genauer erläutert. Detaillierte Informationen über die anderen Formen können unter
http://www.asp.net/aspnet/overview/authentication-and-identity nachgelesen werden.
Beim Verwenden von Individual Accounts wird die ASP.NET Forms Authentication eingesetzt, bei welcher
der Authentifizierungsvorgang aus drei Komponenten besteht:
 User Agent (Browser)
 Forms Authentication Middleware
 Webapplikation
Sobald zum ersten Mal auf eine geschützte Ressource zugegriffen wird, wird der Benutzer auf die Login
Seite umgeleitet. Nachdem der Benutzer die Zugangsdaten eingegeben hat, werden diese von der
Anwendung überprüft und die User Claims erstellt, welche den Benutzernamen und die Rollen des
Benutzers enthalten. Danach werden diese von der Middleware verschlüsselt, kodiert und in ein Ticket
umgewandelt und als Cookie zum Client gesendet. Bei den nächsten Zugriffen wird dieses Ticket von der
Middleware verifiziert, zurück konvertiert und als HttpContext.User Objekt abgespeichert. Über dieses
Objekt kann in der Webapplikation auf den aktuellen Benutzer sowie dessen Rollenmitgliedschaft
zugegriffen werden. [27] Der Ablauf wird in der Tabelle 1 veranschaulicht.
User Agent (Browser)
Forms Authentication
Middleware
Webapplikation
1. Ressource wird aufgerufen
Get /Account/Manage
----------------------->
2. Response Status 401
Da die Ressource eine
Authentifizierung verlangt, wird der
HTTP Code 401 (Client
Unauthorized) zurückgeliefert
<------------401----------3. Die Middleware
konvertiert den HTTP
Code zu 302 (Redirect
29
Secure .NET Development
found) und leitet den
Client zur Login Seite um
<-----------302---------4. Login Seite wird aufgerufen
GET /Account/Login?
ReturnUrl=/Account/Manage
----------------------->
5. Login Seite wird zurückgeliefert
<------------200----------6. Benutzername und
Passwort werden zum Server
gesendet
POST /Account/Login?
ReturnUrl=/Account/Manage
----------------------->
7. Die Webapplikation führt folgende
Aktionen durch
-überprüft die Credentials
- führt die Methode
IdentityAuthenticationManager.SignIn
aus
- leitet den Client auf die ReturnUrl
um
<------------301----------8. Die Middleware
konvertiert die User
Claims in einen Token
und setzt diesen als
Cookie beim Client
<-----------302---------9. Ressource erneut
anfordern, jedoch mit
gesetzten Token in den
Cookies
----------------------->
10. Die Middleware
überprüft und konvertiert
den Token zurück.
----------------------->
Webapplikation erkennt, dass
Benutzer authentifiziert ist und liefert
daher die Ressource zurück.
<------------200----------Tabelle 1: Ablauf einer Forms Authentication [27]
30
Secure .NET Development
Der Vorgang für die Authentifizierung mit einem externen Provider wie Facebook, Google, Microsoft oder
Twitter ist ein klein wenig
anders als in Tabelle 1 gezeigt [27]. Der hierfür notwendige
Authentifizierungsprozess kann unter http://blogs.msdn.com/b/webdev/archive/2013/07/03/understandingowin-forms-authentication-in-mvc-5.aspx nachgelesen werden.
Um den Authentifizierungsprozess aus der Tabelle 1 zu implementieren, sind nur wenige Schritte
notwendig:
 Eine geschützte Ressource muss mit dem Attribut Authorize versehen werden. Dieses Attribut kann
sowohl auf eine Methode als auch auf einen Controller angewendet werden. Wenn nur eine bestimmte
Gruppe auf die Ressource zugreifen darf, so kann auch der Parameter Roles angegeben werden
(siehe Listing 17)
1
2
3
4
5
[Authorize(Roles = „admin“)]
public ActionResult ResetPassword(string id, MessageStates? message)
{
...
}
Listing 17: Authorize Attribut
 Nachdem der Benutzer die Zugangsdaten (Benutzername und Passwort) angegeben hat, müssen diese
überprüft werden. Sind diese korrekt, so werden die User Claims erstellt und der Benutzer angemeldet.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var user = UserManager.Find(model.UserName, model.Password);
if (user != null)
{
var identity = UserManager.CreateIdentity(user,
DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties() {
IsPersistent = isPersistent }, identity);
return RedirectToLocal(returnUrl);
}
else
{
ModelState.AddModelError("", "Invalid username or password.");
}
Listing 18: Implementierung der Forms Authentication
In Listing 18 werden folgende Aktionen durchgeführt:
 Zeile 1 - 2: Es wird überprüft, ob die Kombination von Benutzername und Passwort in der Datenbank
vorhanden ist. Damit das Objekt UserManager einen Zugriff auf die Datenbank hat, muss es zuvor
mit dem Entity Framework Kontext initialisiert werden.
 Zeile 4 – 5: Da der Benutzer gültige Zugangsdaten angegeben hat, werden die User Claims
abgefragt. Diese bestehen aus dem Benutzernamen und den dazugehörigen Rollen/Gruppen.
 Zeile 7 – 8: Die User Claims werden an die Middleware übergeben. Zusätzlich wird mitgeteilt, ob der
Benutzer die Checkbox „Angemeldet bleiben“ aktiviert hat.
31
Secure .NET Development
 Zeile 10: Der Benutzer wird zur gewünschten Ressource geleitet.
 Zeile 14: Wenn der Benutzer ungültige Zugangsdaten eingegeben hat, wird eine entsprechende
Fehlermeldung zurückgeliefert.
3.6.
ASP.NET Web API
Bei ASP.NET Web API handelt es sich um ein typisches Webservice. Ein Webservice ist eine
Softwareanwendung, welche für die direkte Maschine-zu-Maschine (M2M) Kommunikation verwendet wird.
Dabei wird der Dienst von einem Webserver betrieben. Da der Zugriff über standardisierte Protokolle wie
HTTP und XML gesteuert wird, können solche Dienste für die Kommunikation in heterogenen Netzwerken
eingesetzt werden. [28] Häufig werden Webservices als Schnittstelle zwischen den Clients und einer
Datenbank verwendet, da hiermit ein Zugriff von unterschiedlichen Geräten auf eine Datenbank möglich
wird.
Webservices, vor allem solche, die in öffentlichen Netzen angeboten werden, sind einer Vielzahl von
Angriffen ausgesetzt. Insbesondere Angriffe, die die Verfügbarkeit von Systemen vollständig eliminieren
können, die sogenannten Denial-of-Service (DOS) Attacken, stellen eine große Gefahr dar. [29] Aber auch
durch unbefugte Zugriffe auf Webservices, welche als Schnittstellen zu sensiblen Daten fungieren, können
schwerwiegende Schäden entstehen. Daher müssen Maßnahmen wie Authentifizierung, Validierung und
DOS Abwehrmechanismen eingesetzt werden.
 Authentifizierung
Da .NET Webservices (Web API) im Aufbau sehr viele Gemeinsamkeiten mit .NET Webapplikationen
haben, kann auch der gleiche Authentifizierungsprozess verwendet werden. Daher können die
Informationen unter 3.5 auch für Web APIs angewendet werden.
 Validierung
Damit ein Webservice gegen manipulierte Eingabedaten geschützt ist, um beispielsweise gegen SQL
Injection resistent zu sein, können die gleichen Maßnahmen wie bei den Webapplikationen verwendet
werden: Um sich dagegen zu schützen, müssen sichere Datenbankzugriff verwendet werden (siehe
3.2.2). Das Einschleusen von Script Code kann durch das Attribut [ValidateInput(true)]
verhindert werden (siehe 3.1).
 DOS Protection
Bei einem verteilten DoS Angriff werden die Webserver von einer großen Anzahl von Rechnern mit
vielen Anfragen überflutet, wodurch die Server überlastet werden und dadurch Anfragen nicht oder nur
begrenzt beantworten können. Um dies zu vermeiden, könnte eine Firewall nur autorisierte IP Adressen
durchlassen, um die Anzahl der Anfragen zu minimieren. [29] Das funktioniert aber nicht immer, da
Webservices sehr oft für die Öffentlichkeit bereitgestellt werden. Daher müssen die angebotenen
Dienste so entwickelt werden, dass keine Überlast produziert werden kann.
ASP.NET Web APIs können in Kombination mit Open Data Protocol (OData) als REST-basierte
Datendienste fungieren. Dadurch können Ressourcen, welche über URIs (Uniform Resource Identifiers)
identifiziert werden und in einem Datenmodell definiert sind, mittels HTTP-Nachrichten veröffentlicht und
32
Secure .NET Development
bearbeitet werden. [30] Dadurch ergibt sich der Vorteil, dass nicht für jeden Datenbankzugriff eine eigene
Methode geschrieben werden muss (GetAllProducts(), GetProductsById (…), GetProductsByName (…),
…). Um beispielsweise alle Produkte sortiert abzurufen, würde folgender Aufruf genügen:
http://<domain>/webservice.svc/products?$orderby=name
Im Webservice muss keine eigene Methode implementiert werden, da OData die übergebene Anweisung
in eine Datenbankabfrage konvertiert und das Ergebnis als JSON oder XML zurücksendet. Das Gefährliche
an dieser Art ist, dass Angreifer einen Webserver mit einer Reihe von komplexen Anweisungen schnell zu
einer hohen Auslastung bringen können. Würde es zum Beispiel 1 Million Produkte geben und die vorherige
Anfrage würde alle 500 Millisekunden gesendet werden, so würde der Server schnell an seine Grenzen
stoßen. Um dies zu vermeiden, können folgende Mechanismen implementiert werden: [31]
 Anzahl der Datensätze einschränken
Damit bei großen Datenmengen nicht alle Daten auf einmal an die Client übertragen werden, sollte man
Pagging verwenden, um die Daten stückweise auszuliefern. Mit dem nachfolgenden Attribut würden
maximal 100 Datensätze zurückgeliefert werden.
1
2
[Queryable(PageSize = 100)]
public IQueryable<Product> Get()
Listing 19: OData - Anzahl der Datensätze einschränken
 Nur bestimmte Operationen zulassen
Damit beispielsweise keine OrderBy Anweisungen gesendet werden können, sondern nur
zugelassene Operationen, müssen diese explizit erlaubt werden.
1
2
[Queryable(AllowedQueryOptions = AllowedQueryOptions.Filter |
AllowedQueryOptions.Top)]
public IQueryable<Product> Get()
Listing 20: OData - Operationen einschränken
Es gibt noch eine Menge weitere Einschränkungen wie zum Beispiel das Zulassen von bestimmte
Arithmetische Optionen. Diese können unter http://blogs.msdn.com/b/webdev/archive/2013/02/06/protectyour-queryable-api-with-validation-feature-in-asp-net-web-api-odata.aspx abgerufen werden.
33
Secure .NET Development
4. Windows Communication Foundation (WCF)
Seit 2006 liefert Microsoft mit dem .NET Framework 3.0 die Windows Communication Foundation (WCF)
mit, wodurch es möglich wurde, verteilte Applikationen auf Basis von SOA (Service-oriented Architecture)
zu schreiben. Zuvor gab es dafür zwar auch schon Technologien wie .NET Remoting, Message Queuing
(MSMQ) oder Enterprise Services, jedoch konnten diese immer nur für bestimmte Anforderungen genutzt
werden. Daher vereinigte Microsoft mit WCF alle diese Technologien zu einem Guss, um ein zentrales
Framework für viele Situationen bereitzustellen. [32, pp. 327, 328] In der Tabelle 2 werden alle
zusammengefassten Technologien von WCF gezeigt.
Technologie
ASMX
Anforderung
Interoperable
Web Services
Binary .NET .NET
Communication
Distributed
Transactions,
etc.
.NET
Remoting
Enterprise
Services
WSE
System.
Messaging
System.
NET
X
WCF
X
X
X
X
Support für WS* Specifications
X
X
Queued
Messaging
X
X
RESTful
Communication
X
x
x
Tabelle 2: Technologien von WCF [33, p. 7]
4.1.
Endpoints
Um ein WCF Service zu veröffentlichen, muss ein sogenannter Endpoint eingerichtet werden. Dieser
besteht aus den drei Komponenten Address, Contract und Binding. Auch der Client benötigt diese
Informationen, um mit dem Service kommunizieren zu können. [32, p. 340]
 Address – Wo finde ich den Dienst?
Eine Adresse besteht aus dem Transport Protokoll, dem Maschinennamen, einem Port und einem Pfad.
Die Syntax einer Adresse lautet daher: Protokoll://<Maschinenname>[:port]/>Pfad zum
Service>
34
Secure .NET Development
WCF unterstützt dabei mehrere Protokolle, welche je nach Anforderung eingesetzt werden können: [32,
pp. 340, 341]
 HTTP: das häufigste verwendete Protokoll, um auf ein WCF Service zuzugreifen. Ein Vorteil ist, dass
durch einen Browser auf das Service zugegriffen werden kann.
Adresse: http://<domain>/<Pfad zum Service>
 Named Pipes: Dieses Protokoll wird für Inter-Prozess oder In-Prozess Kommunikationen verwendet.
Adresse: net.pipe://example.com/Products/GetAllProducts
 TCP: ähnlich wie das HTTP Protokoll, kann jedoch nicht über einen Webbrowser aufgerufen werden.
Adresse: net.tcp://example.com/Products/GetAllProducts
 MSMQ: Message Queues haben den Vorteil, dass Daten kurzzeitig zwischengespeichert werden
können. Somit kann ein Server für kurze Zeit offline sein, da er die Daten nachträglich aus der Queue
empfängt. Bei diesem Protokoll gibt es keine Portangabe.
Adresse: net.msmq://example.com/Products/GetAllProducts
 Contract – Was wird zwischen dem Client und dem Service ausgetauscht? [34]
Contracts sind Interfaces und Datenstrukturen, die angeben, welche Operationen und Daten ein Service
anbietet. Es gibt drei Typen von Contracts:
 Service Contract: beschreibt eine Reihe zusammenhängender Operationen in einem gemeinsamen
Interface. Um eine Klasse als Service anzubieten, muss das Attribut [ServiceContract] gesetzt
werden. Zusätzlich muss jede Methode, welche veröffentlich werden soll, mit dem Attribut
[OperationContract] gekennzeichnet werden. (siehe Listing 21)
 Data Contract: Damit komplexe bzw. eigene Datentypen serialisiert werden können, muss bei der
entsprechenden Klasse und den gewünschten Properties das Attribut [DataContract] gesetzt
werden.
 Message Contract: Um mehr Kontrolle über die von WCF generierten SOAP Nachrichten zu
bekommen, können MessageContracts verwendet werden. Dazu muss über die Klasse das Attribut
[MessageContract] gesetzt werden. Die gewünschten Properties könnten dann entweder mit dem
Attribut [MessageBody] oder [MessageHeader] gekennzeichnet werden.
1
2
3
4
5
6
7
8
9
[ServiceContract]
public interface IRandomService
{
[OperationContract]
int GetRandomNumber();
[OperationContract]
int GetRandomNumberInRange(int min, int max);
}
Listing 21: Service Contract
 Binding – Wie kommuniziere ich mit dem Dienst?
35
Secure .NET Development
Mit den Bindings wird festgelegt, wie ein Dienst mit der Außenwelt kommuniziert. Dabei werden Aspekte
wie die verwendete Kommunikationstechnik (HTTP, TCP, …), die Kodierung (Binär, Text, XML, …), die
eingesetzte Verschlüsselungstechnik und vieles mehr beschrieben. Da es sehr viele
Konfigurationsparameter
gibt,
können
vom
Framework
bereitgestellte
Bindings
wie
BasicHttpBinding, NetTcpBinding, usw. verwendet werden. [3, p. 104] Details über alle Bindings
können unter http://msdn.microsoft.com/en-us/library/ms730879(v=vs.110).aspx abgerufen werden.
Die Parameter Adress und Binding können sowohl im Quellcode also auch in einer Konfigurationsdatei
angegeben werden. Beim Verwenden einer Konfigurationsdatei ergibt sich der Vorteil, dass bei
Änderungen nicht neu kompiliert werden muss. [3, p. 104] Um einen Endpoint für das Service und den
Client zu erstellen, ist folgender Konfigurationseintrag notwendig:
Server
1
2
3
4
5
6
7
8
9
10
11
<system.serviceModel>
<services>
<service name="WcfService.RandomService">
<endpoint address="net.tcp://localhost:8732/Random"
binding="netTcpBinding" contract="WcfService.IRandomService"/>
<endpoint address="net.tcp://localhost:8733/mex"
binding="mexTcpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
Listing 22: WCF Endpoint (Service)
In Listing 22 wird folgende Konfiguration festgelegt:
 Zeile 3: Die Klasse RandomService wird als Service veröffentlich. In dieser Klasse wurden die
Methoden des Service Contracts aus Listing 21 implementiert.
Zeile 4 – 5: Mit dem Endpoint wird festgelegt, dass die Kommunikation über TCP läuft. Die Konsumenten
könnten dabei alle Operationen nutzen, welche im Contract WcfService.IRandomService definiert
wurden. Zusätzlich wird noch die Adresse für den Dienst angegeben.
 Zeile 7 – 8: Dieser Endpoint ist für den Austausch von Metadaten notwendig. Der Endpoint ist nicht
zwingend für die Funktionalität notwendig, erleichtert aber die Entwicklung von WCF Diensten in Visual
Studio enorm.
Client
1
2
3
4
5
6
<system.serviceModel>
<client>
<endpoint address="net.tcp://localhost:8732/Random"
binding="netTcpBinding" contract="RandomService.IRandomService"/>
</client>
</system.serviceModel>
Listing 23: WCF Endpoint (Client)
36
Secure .NET Development
In Listing 23 wird folgende Konfiguration festgelegt:
 Zeile 3 – 4: Um eine Verbindung mit dem WCF Service aus Listing 22 aufbauen zu können, muss am
Client der gleiche Endpoint angegeben werden.
Der große Vorteil von WCF ist nun, dass man zum Beispiel in nur einem Schritt die Übertragungstechnik
ändern kann, ohne den Code anpassen zu müssen. Soll die Kommunikation auf HTTP umgestellt werden,
so muss der Parameter netTcpBinding auf basicHttpBinding sowie das Protokoll in der Adresse
auf http:// geändert werden.
4.2.
Sicherheitsmechanismen
Einer der wichtigsten Punkte bei verteilten Anwendungen ist die Sicherstellung einer sicheren
Kommunikation. Gerade bei der Übertragung von sensiblen Daten über öffentliche Netze müssen Aspekte
wie Vertraulichkeit, Integrität und Authentizität gewährleistet werden. Bei WCF unterscheidet man dabei
zwischen der Transportsicherheit und der Nachrichtensicherheit.
Bei der Transportsicherheit wird der Übertragungskanal entweder mit SSL (Secure Socket Layer) oder
SPNEGO (Simple and Protected GSSAPI Negotiation Mechanism) verschlüsselt. Da SSL durch den
Einsatz im World Wide Web sowie SPNEGO für Integrated Windows Authentication schon lange im Einsatz
sind, haben sich diese Technologien bereits bewährt. Bei der Nachrichtensicherheit wird die Nachricht
selbst verschlüsselt und signiert. [3, pp. 105, 106] Dazu bietet WCF die verschiedenen WS-* Klassen wie
WS-Security, WS-Trust und WS-SecureConversation an. [33, p. 10]
Es kann auch ein Mix von Transportsicherheit und Nachrichtensicherheit durchgeführt werden. So wird
zum Beispiel die Nachricht verschlüsselt, signiert und anschließend über einen SSL Port übertragen, ohne
nochmals verschlüsselt zu werden. Die Verschlüsselung mittels Transportsicherheit wird im Gegensatz zur
Nachrichtensicherheit Stream-basiert durchgeführt. Daher sollte aus Performance Gründen die Chiffrierung
mittels Transportsicherheit realisiert werden. [3, p. 106]
Da die vom WCF bereitgestellten Bindings zum Teil standardmäßig keine Sicherheitsparameter setzen,
muss dies durch weitere Konfigurationsschritte manuell durchgeführt werden. Beim Verwenden von
basicHttpBinding ohne weitere Einstellungen werden keine Sicherheitsmechanismen verwendet. In
der Abbildung 13 wurde die Kommunikation mit einem Sniffer abgehört, um die ausgetauschten Daten
auszulesen. Werden nun beispielsweise Kreditkarteninformationen ausgetauscht, so wäre das eine fatale
Sicherheitslücke. Um dies zu beheben, kann die Flexibilität von WCF genutzt werden: Es muss lediglich
die Konfiguration der Bindings erweitert werden und diese im Endpoint mit dem Parameter
bindingConfiguration verknüpft werden. (siehe Listing 24)
37
Secure .NET Development
Abbildung 13: WCF Kommunikation im Klartext
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<system.serviceModel>
<services>
<service name="WcfService.RandomService">
<endpoint address="https://10.0.0.29:8735/Math"
bindingConfiguration="customBinding" binding="basicHttpBinding"
contract="WcfService.IRandomService" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="customBinding">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
Listing 24: WCF mit Transportsicherheit
Wie in den Zeile 9 – 15 von Listing 24 zu sehen ist, wurde eine benutzerdefinierte Binding erstellt. In dieser
wurden die Parameter für eine Transportsicherheit gesetzt. Dieses Binding ET1(ur)-14(de)4( )25(e)-9s TJE6ETBdadefit
38
Secure .NET Development
4.3.
WCF vs. ASP.NET Web API
WCF Dienste können als Webservice, Stand-Alone Applikation oder Windows Service betrieben werden.
Nun bietet das .NET Framework allerdings auch die ASP.NET Web API (siehe 3.6) zum Entwickeln von
Webservices an. Welche Technologie sollte nun zum Entwickeln eines Webservices verwendet werden?
WCF gilt als sehr mächtiges Framework, da durch die zahlreichen Konfigurationsmöglichkeiten sehr viele
Anforderungen abgedeckt werden können. Dadurch ist es aber auch komplexer als ein einfaches ASP.NET
Webservice. Und genau hier liegt auch der größte Unterschied: ASP.NET Webservices sind im Gegensatz
zu WCF klein, leichtgewichtig und einfach in Betrieb zu nehmen. [37] Um besser entscheiden zu können,
welche Technologie am besten eingesetzt werden soll, werden in der Tabelle 3 die Features
gegenübergestellt:
WCF
Mehrere Übertragungsprotokolle (HTTP, TCP,
UDP)
Mehrere Kodierungsmöglichkeiten (Text, MTOM
und Binär)
Unterstützt WS-* Standards wie Reliable
Messaging, Transactions oder Message Security
Unterstützt Request-Reply, One Way und Duplex
message exchange
Mit .NET Framework mitgeliefert
ASP.NET Web API
Nur HTTP als Übertragungsprotokoll
Daten werden üblicherweise mittels XML oder
JSON serialisiert
Es werden Basis Protokolle und Formate wie
HTTP, SSL, JSON und XML verwendet. Es gibt
keine Unterstützung für höhere Protokolle wie
Reliable Messaging oder Transactions
HTTP basiert auf Request/Response
Ebenfalls im .NET Framework enthalten, ist
jedoch Open Source
Tabelle 3: WCF Webservice vs. ASP.NET Web API [37]
ASP.NET Web API wird sehr stark weiterentwickelt, da leichtgewichtige Dienste durch die starke
Verbreitung von mobilen Geräten immer mehr an Bedeutung gewinnen. Daher sollte man bei neuen
Projekten die ASP.NET Web API bevorzugen, wenn diese alle Anforderungen erfüllen kann.
39
Secure .NET Development
5. Kryptographie
In diesem Kapitel geht es um kryptografische Konzepte in .NET. Kryptographie ist die Lehre von der Verund Entschlüsselung. Dadurch können vertrauliche Daten über unsichere Netze wie beispielsweise das
Internet übertragen werden, ohne dass diese von unberechtigten Personen gelesen werden können. Um
dies zu erreichen, werden Verschlüsselungsalgorithmen oder Chiffriercodes auf die Daten angewendet,
welche aus mathematischen Funktionen zur Ver- und Entschlüsselung bestehen. Die Sicherheit der
verschlüsselten Daten ist dabei von der Stärke des Verschlüsselungsalgorithmus und der Geheimhaltung
sowie der Länge des Schlüssels abhängig. [38, p. 3]
In der modernen Kryptographie werden folgende Ziele verfolgt, um Informationen zu schützen: [39, pp. 14]
 Vertraulichkeit: Nur berechtigte Personen dürfen Zugriff auf den Inhalt von Nachrichten bekommen.
 Integrität: Es muss für den Empfänger nachprüfbar sein, dass er die Nachricht unversehrt erhalten hat.
 Authentizität: Die Identität des Absenders einer Nachricht soll für den Empfänger nachprüfbar sein.
 Verbindlichkeit: Ein Absender einer Nachricht soll seine Urheberschaft später nicht verleugnen können.
5.1.
Symmetrische Verfahren
Bei symmetrischen Verschlüsselungen wird für die Ver- und Entschlüsselung ein einziger Schlüssel
benötigt, d.h. sowohl der Absender als auch der Empfänger müssen denselben Schlüssel besitzen. Dieses
Verschlüsselungssystem ist sehr schnell. Der Nachteil ist jedoch der Schlüsselaustausch: Bekommt ein
Angreifer bei der Schlüsselverteilung Zugriff auf den Schlüssel, so kann er alle Daten entschlüsseln. Daher
sollte die symmetrische Verschlüsselung nur eingesetzt werden, wenn eine der folgenden Gegebenheiten
zutrifft: [38, p. 3]
 Es werden nur lokale Daten verschlüsselt, welche nicht übertragen werden.
 Es wird ein sicheres Protokoll für den Schlüsselaustausch verwendet, wie z.B. Diffie-Hellman.
 Die symmetrische Verschlüsselung wird in Kombination mit einer asymmetrischen Verschlüsselung
durchgeführt.
Für symmetrische Verschlüsselungen stehen bekannte Algorithmen wie
 Advanced Encryption Standard (AES) oder auch Rijndael-Algorithmus: Schlüssellänge 128, 192 oder
256 Bit
 Data Encryption Standard (DES): Schlüssellänge 56 Bit
 Tripple-DES: Schlüssellänge 112 Bit
zur Verfügung.
In dem nachfolgenden Beispiel wird der AES als Verschlüsselungsalgorithmus verwendet. Es wird eine
Client-Server Anwendung erstellt, wo Nachrichten vom Client verschlüsselt an den Server gesendet
werden. Bei Bedarf können auch andere Algorithmen eingesetzt werden. Beachten Sie jedoch, dass
Schlüssel mit weniger als 100 Bit bei symmetrischen Verfahren als nicht sicher eingestuft werden.
40
Secure .NET Development
Server
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
static void Main(string[] args)
{
try
{
TcpListener tcpListener = new TcpListener (IPAddress.Parse
("127.0.0.1"), 8001);
tcpListener.Start();
Socket socket = tcpListener.AcceptSocket();
NetworkStream nStream = new NetworkStream(socket);
StreamReader reader = new StreamReader(nStream);
byte[] iv = Convert.FromBase64String(reader.ReadLine());
byte[] key = Convert.FromBase64String(reader.ReadLine());
while (true)
{
string msg = streamreader.ReadLine();
Console.WriteLine("Received: " + DecryptData(msg, iv, key));
}
reader.Close();
nStream.Close();
socket.Close();
tcpListener.Stop();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
public static string DecryptData(string input, byte[] iv, byte[] key)
{
MemoryStream tmpStream = new MemoryStream();
RijndaelManaged aes = new RijndaelManaged();
CryptoStream cs = new CryptoStream(tmpStream,
aes.CreateDecryptor(key, iv), CryptoStreamMode.Write);
byte[] data = Convert.FromBase64String(input);
cs.Write(data, 0, data.Length);
cs.FlushFinalBlock();
return Convert.ToBase64String(tmpStream.ToArray());
}
Listing 25: TCP Server für AES Kommunikation
Im Listing 25 werden folgende Aktionen durchgeführt:
41
Secure .NET Development
 Zeile 5 - 7: Der TCP Port 8001 wird geöffnet.
 Zeile 9: Es wird auf einen Verbindungsaufbau eines Clients gewartet. Sobald eine Verbindung aufgebaut
wird, wird ein Socket erzeugt.
 Zeile 11 – 12: Es wird ein Übertragungskanal erstellt, über welchen die gesendet Daten vom Client
gelesen werden.
 Zeile 14 – 15: Der Server erwartet in den ersten beiden Nachrichten den Initialisierungsvektor (IV) und
den Schlüssel, die für die nachfolgende Entschlüsselung verwendet werden sollen.
 Zeile 17 – 21: Die gesendeten Daten werden eingelesen und mit dem zuvor erhaltenen IV und Schlüssel
entschlüsselt und ausgegeben.
 Zeile 23 – 26: Der Übertragungskanal und die Verbindung werden geschlossen.
 Zeile 36: Es wird eine Instanz vom Objekt MemoryStream erstellt, welche zum Zwischenspeichern der
entschlüsselten Daten benötigt wird.
 Zeile 37: Es wird eine Instanz vom Objekt RijndaelManaged erstellt, welche zum Entschlüsseln der
Daten benötigt wird.
 Zeile 39 – 40: Es wird eine Instanz vom Objekt CryptoStream erstellt, durch welche die Daten
entschlüsselt werden. Als Parameter müssen der Zielort und der Entschlüsselungsalgorithmus
angegeben werden.
 Zeile 42 – 44: Die Daten werden in ein Byte Array umgewandelt und durch den erstellten
CryptoStream geschickt. Erst durch die Methode Flush() werden die Daten dann entschlüsselt in
den MemoryStream geschrieben.
 Zeile 46: Nun können die entschlüsselten Daten aus dem MemoryStream ausgelesen und
zurückgeliefert werden. Da die Daten als Byte Array abgespeichert wurden, müssen diese zuvor noch
in ein String Element konvertiert werden.
Client
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
static void Main(string[] args)
{
try
{
TcpClient tcpclnt = new TcpClient();
tcpclnt.Connect("127.0.0.1", 8001);
NetworkStream nStream = tcpclnt.GetStream();
StreamWriter writer = new StreamWriter(nStream);
RijndaelManaged aes = new RijndaelManaged();
byte[] iv = aes.IV;
byte[] key = aes.Key;
writer.WriteLine(Convert.ToBase64String(iv));
writer.WriteLine(Convert.ToBase64String(key));
writer.Flush();
while (true)
{
Console.Write("Enter the string to be transmitted : ");
writer.WriteLine(EncryptData(Console.ReadLine(), iv, key));
writer.Flush();
}
42
Secure .NET Development
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
reader.Close();
nStream.Close();
socket.Close();
tcpclnt.Close();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
public static string EncryptData(string input, byte[] iv, byte[] key)
{
MemoryStream tmpStream = new MemoryStream();
RijndaelManaged aes = new RijndaelManaged();
CryptoStream cs = new CryptoStream(tmpStream,
aes.CreateEncryptor(key, iv), CryptoStreamMode.Write);
byte [] data = Convert.FromBase64String(input);
cs.Write(data, 0, data.Length);
cs.FlushFinalBlock();
return Convert.ToBase64String(tmpStream.ToArray());
}
Listing 26: TCP Client für AES Kommunikation
Im Listing 26 werden folgende Aktionen durchgeführt:
 Zeile 5 - 3: Es wird eine Verbindung zum Server aufgebaut.
 Zeile 8 – 9: Es wird ein Übertragungskanal erzeugt, über welchen die Daten zum Server gesendet
werden.
 Zeile 11 – 13: Der Initialisierungsvektor (IV) und der Schlüssel werden erstellt. Diese werden für die
nachfolgende Verschlüsselung verwendet. Um zufällige Werte zu erhalten, werden diese mit dem
RijndaelManaged Objekt erstellt.
 Zeile 15 – 17: Die generierten Werte werden an den Server gesendet. Erst durch die Methode Flush()
werden die Daten tatsächlich übertragen.
 Zeile 19 – 24: Die eingegebenen Daten werden verschlüsselt und an den Server gesendet.
 Zeile 26 – 29: Der Übertragungskanal und die Verbindung werden geschlossen.
 Zeile 39: Es wird eine Instanz vom Objekt MemoryStream erstellt, welche zum Zwischenspeichern der
verschlüsselten Daten benötigt wird.
 Zeile 40: Es wird eine Instanz vom Objekt RijndaelManaged erstellt, welche zum Verschlüsseln der
Daten benötigt wird.
 Zeile 42 – 43: Es wird eine Instanz vom Objekt CryptoStream erstellt, durch welche die Daten
verschlüsselt werden. Als Parameter müssen der Zielort und der Entschlüsselungsalgorithmus
angegeben werden.
 Zeile 45 – 47: Die Daten werden in ein Byte Array umgewandelt und durch den erstellten
CryptoStream geschickt.
43
Secure .NET Development
 Zeile 49: Nun können die verschlüsselten Daten aus dem MemoryStream ausgelesen und
zurückgeliefert werden. Da die Daten als Byte Array abgespeichert wurden, müssen diese zuvor noch
in ein String Element konvertiert werden.
Die Nachrichten werden zwar verschlüsselt vom Client zum Server gesendet, jedoch wurde zuvor der
Schlüssel in Klartext ausgetauscht. Konnte ein Angreifer beispielsweise durch Sniffen den Schlüssel und
den Initialisierungsvektor abgreifen (siehe Abbildung 14), so könnte er alle übertragenen Daten
entschlüsseln.
Abbildung 14: Schlüsselaustausch abhören
In der Abbildung 14 wird in der Client Applikation der generierte Schlüsselt ausgelesen. Zeitgleich wurde
das Sniffing Programm Wireshark gestartet, um alle Netzwerkaktivitäten abzuhören. Wie man erkennen
kann, konnte der generierte Schlüssel unverfälscht ermittelt werden. Um dies zu vermeiden, kann
beispielsweise das Diffie-Hellman Protokoll eingesetzt werden.
5.1.1. Diffie-Helman Protokoll
Beim Diffie-Helman Protokoll handelt es sich um den ersten Verschlüsselungsalgorithmus, in dem diskrete
Logarithmen in einem endlichen Feld verwendet werden. Es wurde 1976 von Martin Hellman und Whitfield
Diffie erfunden. [38, p. 70] Das Ziel dieses Algorithmus ist ein sicherer Schlüsselaustausch über ein
unsicheres Kommunikationsmedium. Um dies zu erreichen, müssen folgende Schritte durchgeführt
werden. [39, p. 29]
 Beide Teilnehmer generieren eine Primzahl p und eine natürliche Zahl g. Da diese Zahlen nicht geheim
bleiben müssen, können sie über einen unsicheren Kanal ausgetauscht werden.
44
Secure .NET Development
 Beide Teilnehmer erzeugen jeweils geheim zu haltende Zufallszahlen a bzw. b, welche nicht übertragen
werden.
 Nachdem p und g ausgetauscht wurden, berechnen die Teilnehmer A = ga mod p bzw. B = gb mod p.
Danach wird A und B ausgetauscht.
 Nun können beide Teilnehmer den gemeinsamen Schlüssel berechnen: K = Ba mod p bzw. K = Ab mod
p
Um dieses Verfahren in einer .NET Anwendung zu implementieren, können mitgelieferte Bibliotheken
verwendet werden. Dazu wird das Beispiel aus Listing 25 und Listing 26 folgendermaßen erweitert:
Client
1
2
3
4
5
6
7
8
9
10
11
ECDiffieHellmanCng dh = new ECDiffieHellmanCng();
dh.HashAlgorithm = CngAlgorithm.Sha256;
byte[] publicKey = dh.PublicKey.ToByteArray();
writer.WriteLine(Convert.ToBase64String(publicKey));
writer.Flush();
byte[] srvPublicKey = Convert.FromBase64String (reader.ReadLine());
byte[] key = dh.DeriveKeyMaterial(CngKey.Import(srvPublicKey,
CngKeyBlobFormat.EccPublicBlob));
Listing 27: Diffie-Hellman Implementierung (Client)
Server
1
2
3
4
5
6
7
8
9
10
11
byte[] clientPublicKey = Convert.FromBase64String(reader.ReadLine());
ECDiffieHellmanCng dh = new ECDiffieHellmanCng();
dh.HashAlgorithm = CngAlgorithm.Sha256;
byte[] publicKey = dh.PublicKey.ToByteArray();
writer.WriteLine(Convert.ToBase64String(publicKey));
writer.Flush();
byte[] key = dh.DeriveKeyMaterial(CngKey.Import(clientPublicKey,
CngKeyBlobFormat.EccPublicBlob));
Listing 28: Diffie-Hellman Implementierung (Server)
Im Beispiel von Listing 27 und Listing 28 wird ein Diffie-Hellman Schlüsselaustausch auf Basis von
elliptischen Kurven durchgeführt. Dabei werden folgende Schritte abgearbeitet: [40]
 Client und Server generieren jeweils ein Schlüsselpaar für den Diffie-Hellman Schlüsselaustausch.
 Client und Server konfigurieren jeweils dieselben Parameter der Key Derivation Function (KDF). Eine
KDF ist ein deterministischer Algorithmus, um einen Schlüssel aus einem geheimen Wert abzuleiten.
 Client und Server tauschen den öffentlichen Schlüssel aus.
45
Secure .NET Development
 Client und Server nutzen den öffentlichen Schlüssel des jeweils anderen für die Generierung des
gemeinsamen Schlüssels.
5.2.
Asymmetrische Verfahren
Bei asymmetrischen Systemen werden zur Ver- und Entschlüsselung unterschiedliche Schlüssel
verwendet, die mathematisch miteinander verbunden sind. Dadurch vereinfacht sich das Problem des
Schlüsselaustauschs. Nur der Dechiffrierschlüssel muss geheim gehalten werden, der Chiffrierschlüssel
kann dagegen öffentlich bekannt sein. Diese Verschlüsselungsart wird auch als Public-Key Verfahren
bezeichnet. [3, p. 58]
Die Verschlüsselung ist jedoch aufwendiger und daher langsamer, da bei asymmetrischen Verfahren
längere Schlüssel (mindestens 2048 Bits) als bei symmetrischen Verfahren (mindestens 128 Bits)
verwendet werden und die mathematische Generierung eines Schlüsselpärchens zusätzliche
Rechenleistung in Anspruch nimmt. Aus diesem Grund werden häufig hybride Systeme eingesetzt: [41]
Die Verschlüsselung der eigentlichen Daten erfolgt symmetrisch mithilfe eines Session Schlüssels. Dieser
Schlüssel wird für jede Übertragung generiert, asymmetrisch verschlüsselt und an die eigentliche Nachricht
angehängt. So erhält man die Vorteile beider Systeme: Geschwindigkeit und Sicherheit.
Das erste praktisch eingesetzte asymmetrische kryptographische Verfahren war der 1977 entwickelte RSA.
Der Name ist eine Ableitung von den Erfindern: Ronald Rivest, Adi Shamir und Leonard Adleman. Der
RSA ist inzwischen zum de-facto-Standard für die Public-Key Verschlüsselung geworden und ist somit das
bekannteste und verbreitetste asymmetrische Verfahren. Die Sicherheit des RSA Algorithmus basiert auf
der Faktorisierungsannahme: Die Zerlegung einer großen Zahl in ihre Primfaktoren ist sehr aufwändig,
während das Erzeugen einer Zahl durch Multiplikation von Primzahlen recht einfach ist. [42, pp. 84, 85] Der
RSA kann zusätzlich zur Verschlüsselung auch für Digitale Signaturen verwendet werden. Dadurch können
die Integrität, Authentizität und Verbindlichkeit gewährleistet werden.
5.2.1. Verschlüsselung
Um asymmetrische Verschlüsselungen in .NET Anwendungen zu implementieren, kann die Klasse
RSACryptoServiceProivder vom Namespace System.Security.Cryptography verwendet
werden. Im nachfolgenden Beispiel wird vom Server ein öffentlicher Schlüssel an den Client übertragen.
Alle darauffolgenden Daten werden vom Client mit dem öffentlichen Schlüssel verschlüsselt und mit dem
privaten Schlüssel entschlüsselt. Die Vorgänge für die TCP Verbindung können aus dem Beispiel von
Listing 25 und Listing 26 entnommen werden.
Server
1
2
3
4
5
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);
writer.WriteLine(Convert.ToBase64String(rsa.ExportCspBlob(false)));
writer.Flush();
46
Secure .NET Development
6
7
8
9
10
11
12
13
14
while (true)
{
string secureContent = streamreader.ReadLine();
byte[] decryptBytes = rsa.Decrypt (Convert.FromBase64String(
secureContent), false);
Console.WriteLine("Received: " + Encoding.UTF8.GetString (
decryptBytes));
}
Listing 29: RSA Verschlüsselung (Server)
In Listing 29 werden folgende Aktionen durchgeführt:
 Zeile 1: Es wird eine Instanz der Klasse
gewünschten Schlüssellänge initialisiert.
RSACryptoServiceProvider erstellt und mit der
 Zeile 3 – 4: Die RSA Parameter inklusive des öffentlichen Schlüssels werden mit der Methode
ExportCspBlob ausgelesen und an den Client gesendet.
 Zeile 6 – 14: Nachrichten vom Client werden empfangen, entschlüsselt und ausgegeben. Da die Instanz
von RSACryptoServiceProvider den privaten Schlüssel hält, kann einfach die Methode Decrypt
aufgerufen werden.
Client
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
byte[] publicKey = Convert.FromBase64String(reader.ReadLine());
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportCspBlob(publicKey);
while (true)
{
Console.Write("Enter the string to be transmitted : ");
byte[] message = rsa.Encrypt(Encoding.UTF8.GetBytes(
Console.ReadLine()), false);
streamwriter.WriteLine(Convert.ToBase64String (message));
streamwriter.Flush();
}
Listing 30: RSA Verschlüsselung (Client)
In Listing 30 werden folgende Aktionen durchgeführt:
 Zeile 1: Die RSA Parameter inklusive des öffentlichen Schlüssels werden vom Server empfangen.
 Zeile 3 – 4: Es wird eine Instanz der Klasse RSACryptoServiceProvider erstellt und die
empfangenen Parameter werden importiert. Dadurch ist der öffentliche Schlüssel für die spätere
Entschlüsselung bekannt.
 Zeile 6 – 15: Die Daten werden von der Konsole eingelesen, verschlüsselt und an den Server gesendet.
47
Secure .NET Development
5.2.2. Digital Signieren
Wie bereits erwähnt, können Daten mithilfe von asymmetrischen Verfahren signiert werden, um die
Datenintegrität und die Identität des Absenders überprüfen zu können. Eine digitale Unterschrift hat
dieselbe Aufgabe wie eine Unterschrift von Hand, hat jedoch den Vorteil, dass sie nahezu fälschungssicher
ist und außerdem den Inhalt der Informationen und die Identität des Unterschreibenden bescheinigt [38, p.
11]
Auch beim digitalen Signieren wird ein Schlüsselpaar, also ein öffentlicher und ein privater Schlüssel
erzeugt. Um eine Nachricht zu signieren, muss der Sender zuerst einen Hashwert der zu sendenden
Information generieren. Eine Hashfunktionen generiert aus einer beliebig großen Eingabe eine
Zeichenfolge fixer Länge. Der Hashwert wird danach mit dem privaten Schlüssel verschlüsselt und an die
Nachricht angehängt. Der Empfänger erstellt ebenfalls einen Hashwert über die erhaltene Nachricht ohne
die Signatur. Zusätzlich entschlüsselt er die Signatur und vergleicht die beiden Werte. Bei einer
Übereinstimmung weiß man, dass die Nachricht nicht verändert wurde. [39, pp. 11-12] Um die Identität
feststellen zu können, muss das Schlüsselpaar einer Person zugeordnet werden. Dazu werden
üblicherweise Zertifikate verwendet, mit denen vertrauenswürdige Stellen diese Zuordnung bestätigen
(siehe 5.3).
In .NET Applikationen kann zum Signieren wieder die Klasse RSACryptoServiceProvider benutzt
werden, welche folgende Methoden bereitstellt: [3, p. 93]
 SignData: Diese Methode generiert einen Hashwert von den übergebenen Daten und signiert diesen.
Als Parameter muss dazu der gewünschte Hash-Algorithmus übergeben werden.
 SignHash: Diese Methode signiert einen übergebenen Hashwert. Die Methode kommt zum Einsatz,
wenn der Hashwert separat berechnet werden soll.
 VerifyData: Diese Methode überprüft eine mit SignData erstellte Signatur.
 VerifyHash: Diese Methode überprüft eine mit SignHash erstellte Signatur.
Client:
1
2
3
4
5
6
7
8
9
10
11
12
byte[] message = Encoding.UTF8.GetBytes („Inhalt eines Dokuments“);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
byte[] signature = rsa.SignData(message, new
SHA1CryptoServiceProvider());
rsa.Clear();
byte[] publicKey = rsa.ExportParameter (false);
// Send public key + message + signature to the server
Listing 31: RSA Signatur erstellen
In Listing 31 werden folgende Schritte durchgeführt:
48
Secure .NET Development
 Zeile 1: Die zu signierende Nachricht wird in ein Byte Array umgewandelt
 Zeile 3: Erzeugen einer RSACryptoServiceProvider Instanz samt Schlüsselpaar
 Zeile 5 – 6: Erzeugen der Signatur: Es wird zuerst ein Hash mithilfe des SHA1 Algorithmus der Nachricht
generiert, welcher dann mit dem privaten Schlüssel signiert wird.
 Zeile 8: Vertrauliche Daten werden gelöscht.
 Zeile 10: Der öffentliche Schlüssel wird exportiert, da dieser dem Empfänger zur Verfügung gestellt
werden muss.
 Zeile 12: Die Daten (öffentlicher Schlüssel, Signatur und die Nachricht) werden an den Empfänger
übermittelt. Um Daten beispielsweise via TCP Verbindung zu versenden, könnten die Schritte den
Beispielen in Listing 25 und Listing 26 entnommen werden.
Server:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
byte[] publicKey = // Receive public key from client
byte[] message = // Receive message from the client
byte[] signature = // Receive signature from client
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.importParameters(publicKey);
boolean isSignatureCorrect = rsa.VerifyData(message, new
SHA1CryptoServiceProvider(),signature);
rsa.Clear();
if (isSignatureCorrect)
{
...
}
else
{
...
}
Listing 32: RSA Signatur überprüfen
In Listing 32 werden folgende Schritte durchgeführt:
 Zeile 1: Die Daten (öffentlicher Schlüssel, Signatur und die Nachricht) werden empfangen und
abgespeichert.
 Zeile 5 - 6: Es wird eine Instanz der Klasse RSACryptoServiceProvider erstellt und der
empfangenen Schlüssel importiert. Dadurch ist der der öffentliche Schlüssel für die Verifizierung der
Signatur bekannt.
 Zeile 8 – 6: Die Signatur und die erhaltene Nachricht werden verglichen. Dadurch kann festgestellt
werden, ob der Inhalt verändert wurde.
 Zeile 11: Vertrauliche Daten werden gelöscht.
 Zeile 13 – 20: Je nachdem, ob die Signatur korrekt war, können die gewünschten Aktionen durchgeführt
werden.
49
Secure .NET Development
5.3.
Digitale Zertifikate
Ein digitales Zertifikat kann mit einem Personalausweis in elektronischer Form verglichen werden: Bei
einem Personalausweis bestätigt eine vertrauenswürdige Stelle wie zum Beispiel das Meldeamt, dass die
Unterschrift auf dem Ausweis auch tatsächlich zu der Person gehört, deren Daten und Bild sich auf dem
Ausweis befinden. Bei einem Zertifikat bestätigen vertrauenswürdige Stellen wie beispielsweise GlobalSign
die Echtheit von Angaben. [43]
Digitale Zertifikate enthalten Informationen wie den Namen des Inhabers, dessen öffentlichen Schlüssel,
eine Gültigkeitsdauer und den Namen der Zertifizierungsstelle. Diese Informationen werden in einer ASN.1
(Abstract Syntax Notation One) codierten binären Datei abgespeichert. Um Zertifikate zwischen
unterschiedlichen Systemen auszutauschen, muss anstelle der binären Datei ein standardisiertes Format
verwendet werden. Hierzu hat sich das Form X.509 durchgesetzt, welches in RFC 3280 beschrieben ist.
[39, p. 18]
Beim Austausch von Zertifikaten wird gewöhnlich zwischen zwei Formaten unterschieden:
 .cer
Hier handelt es sich um ein signiertes X.509 Zertifikat, welches den öffentlichen Schlüssel und
zusätzliche Daten wie beispielsweise die Zertifizierungsstelle enthält. Dieses wird gewöhnlich an den
Kommunikationspartner gesendet, damit dieser die Daten mit dem öffentlichen Schlüssel verschlüsseln
kann.
 .pfx (Personal Information Exchange)
Hier handelt es sich um ein Zertifikat und den dazugehörigen privaten Schlüssel. Solche Dateien sind
sehr vertraulich und werden normalerweise zum Importieren von Schlüsselpaaren auf einem Server
verwendet.
Um ein Zertifikat zu erhalten, gibt es zwei Möglichkeiten: [44]
 Wenn das Zertifikat für Internet Szenarien verwendet wird, wird es in den meisten Fällen von einer
vertrauenswürdigen Zertifizierungsstelle (CA) angefordert. Solche Zertifikate sind zwar mit Kosten
verbunden, haben aber den Vorteil, dass bekannte Browser und Betriebssysteme diese Zertifikate als
vertrauenswürdig einstufen.
 Wenn das Zertifikat nur für Intranet Szenarien verwendet wird, kann eine eigene Zertifizierungsstelle
eingerichtet werden, welche auf dem Client als vertrauenswürdig eingestuft wird. Dadurch können
Zertifikate selbst erstellt werden. Solche Zertifikate werden auch für B2B Anforderungen eingesetzt.
In
.NET
wird
das
Zertifikat
durch
die
Klasse
X509Certificate2
im
System.Security.Crytography.X509Certificates Namensraum repräsentiert. Auf Zertifikate
kann entweder über den Windows-Zertifikatsspeicher oder über eine Datei (.cer, .pfx) zugegriffen werden.
Mithilfe des Zertifikatsspeichers könnten Zertifikate und ihre dazugehörigen privaten Schlüssel auf
verschiedenen Geräten wie z. B. Festplatten, USB-Tokens oder Smartcards gespeichert werden. Der
Speicher abstrahiert dabei den physikalischen Speicherort, wodurch immer auf die gleiche Weise
zugegriffen werden kann, egal wo das Zertifikat schlussendlich gespeichert ist. Dabei gibt es auf einem
Windows System immer zwei Speichertypen: [3, pp. 205, 206]
50
Secure .NET Development
 Benutzerzertifikatsspeicher: Dieser wird nur für den jeweils angemeldeten Benutzer verwendet und
kann mit dem Befehl certmgr.msc aufgerufen werden.
 Computerzertifikatsspeicher: Dieser Speicher wird von Windows Computerkonten wie NETZWERK,
LOKALER DIENST und LOKALES SYSTEM verwendet. Zusätzlich können damit Zertifikate oder
Schlüssel für mehrere Konten gemeinsam bereitgestellt werden.
Wie in Abbildung 15 veranschaulicht, ist der Speicher in verschiedene Unterelemente unterteilt: Es gibt
beispielsweise einen Container mit dem Namen „Eigene Zertifikate“, in dem eigenen Zertifikate, welche
einen zugeordneten privaten Schlüssel haben verwaltet werden. Ein anderer Container mit den Namen
„Vertrauenswürdige Stammzertifizierungsstellen“ enthält die Zertifikate aller Zertifizierungsstellen, denen
vertraut wird. [3, pp. 205, 206]
Abbildung 15: Benutzerzertifikatsspeicher
5.3.1. Verschlüsseln
Da nun alle theoretischen Fakten erklärt wurden, wird im nachfolgenden Beispiel mittels einer Client-Server
Applikation das Ver- und Entschlüsseln mit Zertifikaten gezeigt. Die Client Applikation verschlüsselt die
Daten, wodurch auf diesem System das Zertifikat mit dem öffentlichen Schlüssel (.cer) installiert sein muss.
Der Server muss zum Entschlüsseln der Daten einen Zugriff auf den privaten Schlüssel (.pfx) haben. In
diesem Beispiel wurde das Zertifikat sowohl am Client als auch am Server im Benutzerzertifikatsspeicher
unter „Eigene Zertifikate“ gespeichert. Die Schritte zum Senden und Empfangen über einen TCP Port
können dem Beispiel aus Listing 25 und Listing 26 übernommen werden.
Client:
51
Secure .NET Development
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certs = Store.Certificates.Find(
X509FindType.FindByIssuerDistinguishedName, "CN=testing.com", true);
X509Certificate2 cert = null;
if (col.Count > 0)
cert = col[0];
else
return;
while (true)
{
Console.Write("Enter the string to be transmitted : ");
byte[] input = Encoding.UTF8.GetBytes(Console.ReadLine());
ContentInfo plainMessage = new ContentInfo(input);
EnvelopedCms encryptMessage = new EnvelopedCms(plainMessage);
encryptMessage.Encrypt(new CmsRecipient(cert));
writer.WriteLine(Convert.ToBase64String(encryptMessage.Encode()));
writer.Flush();
}
Listing 33: Verschlüsseln mit Zertifikaten
In Listing 33 werden folgende Schritte durchgeführt:
 Zeile 1 – 2: Der Container “Eigene Zertifikate” im Benutzerzertifikatsspeicher wird geöffnet.
 Zeile 4 – 5: In dem geöffneten Container wird nach allen gültigen Zertifikaten gesucht, welche von
“testing.com” herausgegeben wurden. Im ersten Parameter kann eine Reihe von Suchtypen wie Serial
Nummer, öffentlicher Schlüssel, usw. angegeben werden. Der zweite Parameter gibt den
dazugehörigen Suchwert an. Im letzten Parameter wird spezifiziert, dass nur gültige Zertifikate gesucht
werden sollen.
 Zeile 7 – 11: Es wird überprüft, ob ein Zertifikat gefunden wurde. Wenn nicht, so wird das Programm
beendet.
 Zeile 15 – 16: Die Daten werden von der Konsole eingelesen und in ein Byte Array konvertiert.
 Zeile 18: Es wird eine ContentInfo Instanz erzeugt und mit dem Klartext initialisiert. Dies ist
notwendig, da dieses Objekt eine Datenstruktur für Cryptographic Message Syntax (CMS) darstellt.
CMS ist ein weit verbreitetes Format für kryptographische Nachrichten. [45]
 Zeile 19 - 20: Es wird eine EnvelopedCms Instanz erzeugt, welches die verschlüsselten Daten
repräsentiert. Zum Verschlüsseln benötigt das Objekt den Klartext in Form einer ContentInfo Klasse,
welche beim Instanziieren an den Konstruktor übergeben wird. Die Methode Encrypt führt die
Verschlüsselung durch. Als Parameter wird ein Zertifikat mit dem öffentlichen Schlüssel in Form einer
CmsRecipient Klasse übergeben. Intern werden die Daten mit einem zufällig generierten Session Key
symmetrisch verschlüsselt. Der Session Key wird dann mit dem öffentlichen Schlüssel verschlüsselt.
Die zugelieferten Daten enthalten die verschlüsselte Nachricht sowie Informationen über den
öffentlichen Schlüssel, damit beim Entschlüsseln der dazugehörige private Schlüssel zugeordnet
werden kann. [3, p. 215]
 Zeile 22 – 23: Die verschlüsselte Nachricht wird an den Server gesendet
52
Secure .NET Development
Server
1
2
3
4
5
6
7
8
9
10
11
while (true)
{
Byte[] message = Convert.FromBase64String(reader.ReadLine());
EnvelopedCms decryptedMessage = new EnvelopedCms();
decryptedMessage.Decode(message);
decryptedMessage.Decrypt();
Console.WriteLine("Received: " + Encoding.UTF8.GetString(
decryptedMessage.ContentInfo.Content));
}
Listing 34: Entschlüsseln mit Zertifikaten
In Listing 34 werden folgende Schritte durchgeführt:
 Zeile 3: Die verschlüsselten Daten vom Client werden empfangen und in ein Byte Array umgewandelt.
 Zeile 5 – 5: Die chiffrierten Nachrichten werden mithilfe des EnvelopedCms Objekts entschlüsselt. Wie
man sehen kann, muss hierzu kein Zertifikat angegeben werden. Da die verschlüsselten Daten auch
den öffentlichen Schlüssel enthalten, kann die Klasse intern nach dem dazugehörigen privaten
Schlüssel suchen. Voraussetzung ist natürlich, dass das Zertifikat mit dem privaten Schlüssel am
System installiert wurde.
 Zeile 9 – 10: Die entschlüsselten Daten werden in der Konsole ausgegeben.
5.3.2. Digital Signieren
Wie bereits unter 5.2.2 erwähnt, werden Signaturen verwendet, um Daten gegen Manipulation zu schützen.
Dazu wurde bereits ein praktisches Beispiel gezeigt, indem die Daten mit einem SHA1 Hash Algorithmus
und RSA Verschlüsselung signiert wurden. Der Empfänger konnte durch die Signatur überprüfen, ob die
Daten während der Übertragung verändert wurden. Jedoch konnte der Empfänger nicht sicherstellen, ob
der Kommunikationspartner auch wirklich der ist, für den er sich ausgibt (Prüfung der Identität). Bei
sensiblen Tätigkeiten wie dem Senden und Empfangen von Geschäftsnachrichten (E-Mails) oder Online
Banking muss sichergestellt sein, dass auch wirklich mit dem geglaubten Gegenüber kommuniziert wird.
Um dies zu gewährleisten, können digitale Zertifikate verwendet werden. Möchte eine Person Dokumente
oder E-Mails digital unterschreiben, so müssen folgende Schritte durchgeführt werden:
 Die Person muss bei einer Zertifizierungsstelle (Certification Authority, CA) um ein Zertifikat zum
digitalen Signieren ansuchen.
 Bevor die CA ein Zertifikat ausstellt, muss die Identität mittels Personalausweis überprüft werden.
 Nachdem die Identität bestätigt wurde, wird ein Zertifikat mit einem öffentlichen und einem privaten
Schlüssel für den Nutzer erstellt.
 Beim Senden einer E-Mail oder eines Dokuments fügt der Absender eine digitale Signatur hinzu.
53
Secure .NET Development
 Durch die digitale Signatur kann der Empfänger den öffentlichen Schlüssel auslesen. Dadurch kann er
bei der verantwortlichen CA überprüfen, ob es sich tatsächlich um den angegebenen Absender handelt.
 Bei diesem Prozess wird vorausgesetzt, dass der Empfänger der verantwortlichen CA vertraut.
Abbildung 16: E-Mail Signatur überprüfen
In der Abbildung 16 wird die Signatur einer E-Mail überprüft. Dabei soll festgestellt werden, dass die E-Mail
Adresse [email protected] auch wirklich zu der Identität Patrick Riedl gehört. Wie man im dazugehörigen
Zertifikat sieht, wurde von der CA GlobalSign die Identität für Herrn Patrick Riedl bestätigt.
Das Signieren mit Zertifikaten in .NET funktioniert ähnlich wie das Ver- und Entschlüsseln mit Zertifikaten
(siehe 5.3.1). Der einzige Unterschied ist, dass anstelle der Klasse EnvelopedCms nun die Klasse
SignedCms verwendet wird. Um das Beispiel von Listing 33 und Listing 34 mit einer Signatur zu erweitern,
müssen folgende Anpassungen durchgeführt werden:
Client:
1
2
3
4
5
6
ContentInfo content = new ContentInfo(input);
SignedCms signedMessage = new SignedCms(content);
signedMessage.ComputeSignature (new CmsSigner(cert));
byte[] signedBytes = signedMessage.Encode();
// Encrypt und transfer signedByte to the server
Listing 35: Signatur mit einen Zertifikat erstellen
54
Secure .NET Development
In Listing 35 werden folgende Schritte durchgeführt:
 Zeile 1: Die eingelesenen Daten werden nun vor dem Verschlüsseln signiert. Dazu wird wieder eine
Instanz von ContentInfo erstellt, um die Daten in einer CMS Datenstruktur abzuspeichern.
 Zeile 2 – 3: Um die Daten zu signieren, wird eine Instanz von SignedCms erstellt, welche die signierten
Daten repräsentiert. Zum Signieren benötigt das Objekt den Klartext in Form einer ContentInfo
Klasse, welche beim Instanziieren an den Konstruktor übergeben wird. Die Methode
ComputeSignature generiert den Hashwert und verschlüsselt diesen mit dem privaten Schlüssel.
Als Parameter wird daher ein Zertifikat mit dem privaten Schlüssel in Form einer CmsSigner Klasse
übergeben.
Server:
1
2
3
4
5
6
7
// Decrypt received data
SignedCms signedMessage = new SignedCms();
signedMessage.Decode(encryptedMessage.ContentInfo.Content);
signedMessage.CheckSignature(false);
foreach (SignerInfo signer in signedMessage.SignerInfos)
Console.WriteLine("Aussteller " + signer.Certificate.IssuerName.Name);
Listing 36: Signatur überprüfen
In Listing 36 werden folgende Schritte durchgeführt:
 Zeile 1: Die Daten werden empfangen und müssen mit dem privaten Schlüssel entschlüsselt werden.
(siehe Listing 34) Erst danach kann eine Integritätsprüfung durchgeführt werden.
 Zeile 3: Um nun die Signatur und das Zertifikat zu überprüfen, wird die Klasse SignedCms verwendet.
Um eine Überprüfung zu starten, müssen zuvor die CMS/PKCS #7 Daten deserialisiert werden.
 Zeile 4: Nun können die Signatur und das Zertifikat überprüft werden. Möchte man nur die Signatur
überprüfen, so muss der Parameter true übergeben werden. Tritt bei der Validierung ein Fehler auf,
so wird eine Exception ausgelöst.
 Zeile 5 – 6: Über das SignedCms Objekt kann auch auf das dazugehörige Zertifikat zugegriffen
werden. Zum Demonstrieren wird hier der Aussteller des Zertifikats ausgegeben.
55
Secure .NET Development
6. Reverse Engineering
Beim Reverse Engineering wird versucht, einen kompilierten Code in den originalen Quellcode zurück zu
bringen. Dadurch können Angreifer eine Menge an Informationen gewinnen: Es können logische Abläufe,
eingesetzte Methoden oder sensible Informationen wie hartcodierte Passwörter ausgelesen werden.
Zusätzlich kann durch Reverse Engineering das Know-How gestohlen werden, wodurch ein großer
Schaden entstehen kann. [46]
Das Dekompilieren von Unmanaged Code wie C/C++ Anwendungen ist sehr schwierig, da beim
Kompilieren der Maschinencode generiert wird. Bei Managed Applikationen wie .NET ist es hingegen sehr
einfach, da nur ein Zwischencode (MSIL) erzeugt wird, welcher dann vom Just-in-time Compiler in den
Maschinencode übersetzt wird. (siehe 2.1) Da der MSIL Code sehr gut dokumentiert ist, gibt es einige
Tools, mit denen eine .NET DLL (Dynamic Link Library) oder eine EXE (Executable) rückwärtskompiliert
werden kann. [47] Dazu werden sowohl kommerzielle als auch kostenlose Programme angeboten:
 JetBrains dotPeek: kostenloser .NET Decompiler
 Dotnet IL Editor (DILE): kostenlos – ermöglicht das Dekompilieren und Debuggen von .NET
Anwendungen
 ILSpy: kostenloser und Open Source Decompiler
 Redgate .NET Reflector: kommerziell - ermöglicht das Dekompilieren und Debuggen von .NET
Anwendungen
Um nun eine .NET Anwendung zu dekompilieren, muss lediglich eines der genannten Tools geöffnet und
die gewünschte Datei (.dll oder .exe) ausgewählt werden.
56
Secure .NET Development
Abbildung 17: Dekompilierte Applikation
Abbildung 18: Originaler Source Code
57
Secure .NET Development
Wenn man die Abbildung 17 und Abbildung 18 vergleicht, kann man erkennen, dass durch das
Dekompilieren der originale Code ohne große Unterschiede ermittelt werden konnte. So konnten
beispielsweise die Zugangsdaten für die SQL Verbindung ausgelesen werden.
6.1.
Gegenmaßnahmen
Um Applikationen vor Reverse Engineering zu schützen, können sogenannte Obfuscating Techniken
eingesetzt werden. Dadurch wird ein gut lesbarer Quellcode in einen schwer lesbaren Code umgewandelt.
[48] Es gibt zwar keine 100%ige Sicherheit gegen das Dekompilieren, jedoch kann man es durch
Obfuscating einem Angreifer so schwer machen, damit der Aufwand zum Cracken so hoch ist, dass es
nicht mehr interessant ist. Obfuscator führen folgende Operationen durch: [49]
 Symbole umbenennen
Um Informationen wie die Namen von Variablen, Funktionen oder Klassen zu schützen, werden diese
Benennungen in nichts aussagende Namen umgewandelt. Dadurch können Programmroutinen von einem
Angreifer nicht nachvollzogen werden.
 Verschlüsselung von Zeichenketten
Wie in Beispiel von Abbildung 18 zu sehen ist, werden innerhalb des Quellcode die Zugangsdaten zu einer
Datenbank angegeben. Um solche Daten zu schützen, werden Zeichenketten während des Obfuscatings
verschlüsselt.
 Verschlüsselung von Ressourcen
Anwendungen haben in der Regel unterschiedliche Ressourcen wie Grafiken oder Konfigurationsdateien
eingebunden. Um auch diese vor unerlaubten Zugriffen zu schützen, können diese verschlüsselt werden.
 Schutz gegen Reflection
Decompiler nutzen häufig Reflections, um Informationen über eine .NET Anwendung zu gewinnen. Durch
Obfuscating kann eine Applikation so verändert werden, dass beim Benutzen von Reflections ein Fehler
ausgelöst wird.
Je nach eingesetztem Tool für den Obfuscating Prozess werden oftmals noch weitere Features angeboten.
Die meisten Obfuscator sind zwar nicht kostenlos, bieten aber dafür jede Menge an Features zum
Absichern einer Applikation. Zum professionellen Einsatz gehören Tools wie Crypto Obfuscator for .NET
(von LogicNP Software) oder Dotfuscator for .NET (von PreEmptive). Wenn man zum Beispiel den
Obfuscator „Crypto Obfuscator for .NET“ auf das Beispiel von Abbildung 18 anwendet, so würde nach dem
Dekompilieren folgendes Ergebnis erzeugt:
58
Secure .NET Development
Abbildung 19: Reverse Engineering nach Obfuscating
Wie man in der Abbildung 19 sehen kann, wurde der Quellcode so verschleiert, dass weder die Namen für
Variablen oder Funktionen noch der Inhalt der Variablen ersichtlich sind.
59
Secure .NET Development
7. Deployment
7.1.
Konfigurationsdaten
Häufig hat man das Problem, dass zwar grundsätzlich sichere Software eingesetzt wird, jedoch
Konfigurationsdateien mit Zugangsdaten unverschlüsselt abgespeichert werden. Dadurch sind die
Sicherheitsmechanismen der Software überflüssig, da so der Zugriff auf Daten bzw. Dienste auch
außerhalb der Software möglich wird.
Beim Absichern einer Konfiguration muss zwischen Clientanwendungen und Webanwendungen
unterschieden werden: Bei Clientanwendungen muss die Konfiguration auf jedem Computer vorhanden
sein, wo die Anwendung gestartet wird. Dies ist bei Webanwendungen nicht notwendig, da die Applikation
zentral auf einer Maschine (Webserver) läuft.
7.1.1. Clientanwendungen
Kommuniziert eine Clientanwendung (z.B. Desktopapplikation) mit einer Datenbank oder einem
Webservice, so muss die Applikation über die entsprechenden Verbindungsdaten verfügen. Heikle
Informationen wie Zugangsdaten sollten dabei auf keinen Fall im Klartext gespeichert werden, da
ansonsten ein Benutzer die Berechtigungen der Software umgehen kann.
Um dies zu gewährleisten, gibt es zwei Möglichkeiten: Entweder die sensiblen Daten werden in der
Applikation hartcodiert angegeben oder die Konfigurationsdatei wird verschlüsselt. Entscheidet man sich
für den ersten Ansatz, so sollte die Applikation unbedingt vor Reverse Engineering Attacken geschützt
werden (siehe Kapitel 6). Beim zweiten Ansatz ist die Schwierigkeit, dass die Applikation den Schlüssel
zum Entschlüsseln benötigt. Da dieser in den meisten Fällen auch hartcodiert angegeben wird, sollte auch
hier die Applikation gegen das Dekompilieren geschützt werden.
7.1.2. Webanwendungen
Bei Webanwendungen ist dieser Vorgang etwas einfacher, da die Konfiguration und die Applikation zentral
abgelegt sind. Um die Sicherheit der Webanwendung zu erhöhen, können sensible Daten in der web.config
verschlüsselt werden. [50] Sollte ein Angreifer Zugriff auf die Konfigurationsdatei bekommen, so wäre
dieser völlig nutzlos, da er die Daten nicht entschlüsseln könnte.
Die Verschlüsselung wird üblicherweise mit einem bereitgestellten Verschlüsselungsmechanismus
durchgeführt. Dazu kann entweder der RsaProtectedConfigurationProvider oder der
DpapiProtectedConfigurationProvider verwendet werden, wobei standardmäßig der RSA
Algorithmus eingesetzt wird. Beim zweiten Provider wird mithilfe der DPAPI (Data Protection API) ver- und
entschlüsselt. Die DPAPI ist Bestandteil eines Windows Betriebssystem, welches die Aufgabe der
Schlüsselverwaltung übernimmt. Bei Bedarf kann auch ein eigener Provider entworfen und verwendet
werden. [51]
60
Secure .NET Development
Bei jeder Installation des .NET Frameworks wird ein RSA Key Container mit dem Namen
NetFrameworkConfigurationKey mitinstalliert. In diesem befindet sich ein öffentlich/privates
Schlüsselpaar, welches für die Ver- und Entschlüsselung der Konfigurationsabschnitte verwendet wird. [52]
Da dieser Schlüssel bei jeder Installation unterschiedlich ist, kann die Konfiguration nur auf der gleichen
Maschine verwendet werden. Besteht der Bedarf, auf mehreren Maschinen dieselbe verschlüsselte
Konfiguration zu verwenden, so kann ein eigener Container generiert und auf andere Maschinen importiert
werden. [53] Damit aus einer Webanwendung direkt auf die verschlüsselte Konfiguration zugegriffen
werden kann, muss die „Application Pool Identity“ der Webapplikation eine Leseberechtigung für den
entsprechenden Container haben. [51] Dies kann mit Befehl aspnet_regiis durchgeführt werden,
welcher unter C:\Windows\Microsoft.NET\Framework\<Version> zu finden ist:
1
aspnet_regiis -pa "<Name des Container>" "<Benutzername>"
Um Daten in der Konfiguration zu verschlüsseln, muss keine einzige Zeile Code geschrieben werden, da
der gesamte Prozess mit der Konsole durchgeführt werden kann. Dazu muss wieder der Befehl
aspnet_regiss verwendet werden, welcher als Parameter den gewünschten Abschnitt in der
Konfiguration sowie den Name der Webapplikation benötigt:
1
aspnet_regiis -pe "<Konfigurationsabschnitt>" -app "<Webapplikation>"
Um beispielsweise den ConnectionString der Webapplikation „SecureWebapplication“ zu verschlüsseln,
muss der folgende Befehl ausgeführt werden:
1
aspnet_regiis.exe -pe "connectionStrings" -app "SecureWebapplikation"
Möchte man den ConnectionString nachträglich ändern, so muss der Konfigurationsabschnitt zuerst
entschlüsselt und danach entsprechend angepasst werden. Danach kann die Verschlüsslung erneut
durchgeführt werden:
1
7.2.
aspnet_regiis.exe -pd "connectionStrings" -app "SecureWebapplikation"
Strong Names
Bei größeren Softwareprojekten werden Abläufe oder Routinen häufig in Bibliotheken wie DLLs (Dynamic
Link Library) ausgelagert, da diese später in anderen Projekten wiederverwendet werden können. Solche
Bibliotheken werden zur Laufzeit von der jeweiligen Applikation geladen. Würde es einem Angreifer
gelingen, eine Bibliothek so zu manipulieren, dass zusätzlich zum ursprünglichen Code auch noch ein
Schadcode ausgeführt wird, so wäre die Applikation kompromittiert. Um dies zu verhindern, können
Komponenten mit einem sogenannten Strong Name signiert werden. [54] Durch einen Strong Name erhält
eine Komponente eine global eindeutige Identität, welche aus einem Namen (z.B. Name der Bibliothek),
der Version und Kulturinformation sowie einem öffentlichen Schlüssel und einer digitalen Signatur besteht.
[55]
61
Secure .NET Development
Ein Strong Name kann mithilfe des Visual Studio sehr einfach erstellt werden. Dazu sind folgende Schritte
durchzuführen:
 die Eigenschaften des Projekts aufrufen (Rechtsklick auf das Projekt – Eigenschaften/Properties)
 in der linken Spalte den Menüpunkt “Signierung/Signing” auswählen
 die Option “Assembly signieren/Sign the assembly” setzen - Zusätzlich muss ein Key File angegeben
werden, welches den privaten und öffentlichen Schlüssel enthält. Bei Bedarf kann der Schlüssel auch
hier erzeugt werden.
Abbildung 20: Signieren einer .NET Bibliothek
 Die Version und Kulturinformationen können unter “Anwendung – Assembly Informationen” angegeben
werden.
62
Secure .NET Development
Abbildung 21: Information einer Assembly setzen
 Nachdem die Bibliothek erstellt worden, kann diese in andere Applikationen eingebunden werden. Wird
die eingebundene Komponente manipuliert, wird folgende Exception ausgelöst:
Abbildung 22: Exception bei manipulierten Bibliotheken
7.3.
ClickOnce-Bereitstellung
ClickOnce wurde von Microsoft entwickelt und dient zum Verteilen von .NET Anwendungen (WinForms,
WPF) über das Netzwerk. [56] Klein- oder Mittelunternehmen besitzen häufig keine Systeme für Software
Rollouts, wodurch das Verteilen und die Wartung von Applikationen sehr mühsam ist.
Mit ClickOnce kann ein Link bereitgestellt werden, über den sich die Benutzer eine Applikation selbst
installieren können. Dieser benötigt keine Administrationsberechtigungen, da die Anwendung in einem
Benutzerverzeichnis installiert wird. Dadurch kann die Anwendung nur vom aktuellen Benutzer genutzt
werden. Ein weiteres Feature von ClickOnce ist der mitgelieferte Aktualisierungsprozess. Bei jedem Start
einer ClickOnce Anwendung wird überprüft, ob eine neue Version bereitsteht. Wenn ja, wird die alte Version
automatisch deinstalliert und die neue installiert. [56] So können Updates rasch und unkompliziert
ausgerollt werden.
Um eine Anwendung mithilfe von ClickOnce bereitzustellen, müssen folgende Schritte durchgeführt
werden:
 in Visual Studio in die Projekteigenschaften der gewünschten Applikation wechseln
 auf der linken Seite den Menüpunkt „Veröffentlichen/Publish“ auswählen
63
Secure .NET Development
Abbildung 23: Applikation mittels ClickOnce bereitstellen
Informationen zu den Optionen können unter
 http://openbook.galileocomputing.de/visual_csharp_2010/visual_csharp_2010_30_002.htm#mjaa7397
d5ca453f2628726d80fab473f3
 http://msdn.microsoft.com/de-de/library/142dbbz4(v=vs.90).aspx
nachgelesen werden.
Mit ClickOnce werden auch sicherheitstechnische Aspekte wie die Signierung von Anwendungs- und
Bereitstellungsmanifesten unterstützt. Details dazu können unter http://msdn.microsoft.com/enus/library/zfz60ccf(v=vs.80).aspx abgerufen werden.
64
Secure .NET Development
8. Konzeptionierung eines Secure Coding Demonstrators
Im Zuge dieser Arbeit wurde ein .NET Demonstrator entwickelt, um die gezeigten Schwachstellen und
Lösungen auch in Schulungen bzw. Trainings präsentieren zu können.
8.1.
Web Security
Es wurden zwei Webapplikationen entwickelt, welche typische Anwendungsfälle wie Benutzeranmeldung
oder benutzerspezifische Datenverwaltung abbilden. Beide Applikationen besitzen zwar das gleiche Design
und dieselben Funktionalitäten, jedoch wurden bei einer Anwendung die hier beschriebenen Best Practice
Ansätze verwendet. Bei der Anderen wurden auf jegliche Sicherheitsfunktionalitäten verzichtet. Durch ein
ausgeklügeltes Demo-Szenario können die Benutzer die unsichere Anwendung Schritt für Schritt angreifen
und somit unberechtigt Zugriff auf Daten erlangen.
Die Applikation demonstriert ein Portal zum Verwalten von Meilen, wobei die Meilen für ein Prämienmodell
á la Miles and More verwendet werden. Meilen können von Mitarbeitern beantragt werden, indem sie einen
Event Eintrag erstellen. Dieser Eintrag besteht aus einem Eventname und Eventtyp (z.B. Buch gelesen,
Schulung teilgenommen, Wiki-Eintrag geschrieben). Die gesammelten Meilen können dann entweder
gegen Produkte eingetauscht oder an andere Benutzer übertragen werden. Ist der angemeldete Benutzer
Mitglied der Administrator-Rolle, so können administrative Funktionen, wie das Verwalten von Benutzern,
von Produkten, usw. ausgeführt werden. In der Tabelle 4 werden alle Funktionen der Anwendung
aufgelistet.
Funktion
Meilen beantragen
Meilen inklusive Status abrufen
Meilen bearbeiten und entfernen
Status von Meilen vergeben
Meilen an andere Benutzer übertragen
Produkte erstellen, bearbeiten und entfernen
Produkte kaufen
Gekaufte Produkte auflisten
Eventtypen erstellen, bearbeiten und entfernen
Benutzer erstellen und entfernen
Passwort zurücksetzen
Übersicht über alle Meilen-Transaktionen abrufen
Berechtigung
Mitarbeiter, Administrator
Mitarbeiter: nur die eigenen Meilen
Administrator: alle Meilen
Mitarbeiter: nur die eigenen Meilen
Administrator: alle Meilen
Administrator
Mitarbeiter, Administrator
Administrator
Mitarbeiter, Administrator
Mitarbeiter: nur die eigenen Produkte
Administrator: alle Produkte
Administrator
Administrator
Mitarbeiter: nur das eigene Passwort
Administrator: alle Passwörter
Mitarbeiter, Administrator
Tabelle 4: Funktionalitäten der Demo Webapplikation
Um die unsichere Webapplikation nun anzugreifen, können folgende Schritte durchgeführt werden:
 Login: Da unsichere Datenbankzugriffe implementiert wurden, kann hier eine SQL Injection
durchgeführt werden.
65
Secure .NET Development
 Erstellen von Meilen: Da die eingegebenen Daten eins zu eins in die Datenbank übernommen werden,
kann man hier eine XSS Attacke anwenden.
 Auflisten der Meilen: Die aufgelisteten Meilen können mithilfe eines Suchfilters eingeschränkt werden.
Dieser Filter kann für eine SQL Injection missbraucht werden, um beispielsweise Daten von anderen
Benutzern abzufragen. Weiters können Details der Datenbank mittels Blind SQL Injection ermittelt
werden.
 Übertragen von Meilen: Mittels einer CSRF Attacke kann sich ein Angreifer Meilen von seinem Opfer
auf sein Konto übertragen.
 Abrufen der Meilen-Transaktionen: Um die Transaktionsliste von einem anderen Benutzer
anzuzeigen, kann eine Direct Object References Schwachstelle ausgenutzt werden.
Login
Meilen
beantragen
Meilen
abrufen
Meilen
einlösen/übertragen
Transaktionen
abrufen
Abbildung 24: Herkömmlicher Ablauf des Web Security Demonstrators
Login
SQL Injection
Meilen
beantragen
XSS Attacke
Meilen
abrufen
Blind SQL
Injection
Meilen
einlösen/übertragen
CSRF Attacke
Transaktionen
abrufen
Direct Object
Reference Attacke
Abbildung 25: Angriffsvektoren des Web Security Demonstrators
8.2.
Kryptographie
Der Demonstrator für die vorgestellten kryptografischen Techniken besteht aus einer Client und einer
Server Anwendung, welche über einen TCP Port kommunizieren. Für jede Verschlüsselungsart wurde eine
eigene Klasse implementiert, wobei jede Klasse die Methode Start() besitzt. Dadurch können in
Schulungen die Verschlüsselungsarten einfach und schnell präsentiert werden, weil nur die gewünschte
Klasse instanziiert und die Start Methode ausgeführt werden muss. Wie man in Listing 37 sieht, werden
die gerade nicht benötigten Verschlüsselungsalgorithmen auskommentiert, damit nur die gewünschte
Verschlüsselung zum Einsatz kommt. Am Server muss natürlich auch die dazu passende Methode
aufgerufen werden.
1
2
3
4
5
6
7
SymmetricClient symmetricClient = new SymmetricClient();
SymmetricDhClient symmetricDhClient = new SymmetricDhClient();
AsymmetricClient asymmetricClient = new AsymmetricClient();
CertificateClient certEncryptClient = new CertificateClient();
// symmetricClient.Start();
// symmetricDhClient.Start();
66
Secure .NET Development
8
9
// asymmetricClient.Start();
certEncryptClient.Start();
Listing 37: Demonstrator: Start des gewünschten Verschlüsselungsalgorithmus
Da die Kommunikation über TCP läuft, kann ein Netzwerk Sniffer verwendet werden, um die
ausgetauschten Daten zu analysieren.
8.3.
WCF
Gleich wie bei dem Demonstrator für Kryptographie wurde auch für WCF eine Client/Server Applikation
entwickelt. Dadurch können die ausgetauschten Daten mithilfe eines Netzwerk Sniffer nachvollzogen
werden. Somit kann man demonstrieren, dass bei einer unsicheren Endpoint Konfiguration die Daten im
Klartext übertragen werden.
67
Secure .NET Development
9. Zusammenfassung & Ausblick
Anhand dieser Arbeit kann erkannt werden, dass das .NET Framework eine sehr mächtige
Laufzeitumgebung ist, welche eine Menge an Sicherheitsfeatures mitliefert. Es wurde gezeigt, wie typische
Webschwachstellen wie beispielsweise Cross-Site-Scripting oder SQL Injection mittels .NET Framework
verhindert werden können. Weiters wurde gezeigt, wie die Kommunikation mit ASP.NET Webservices und
WCF Anwendungen sicher umgesetzt werden kann. Auch das Thema Kryptographie wurde detailliert
behandelt. Dazu wurden .NET Bibliotheken sowohl theoretisch als auch praktisch vorgestellt, um Daten zu
verschlüsseln, entschlüsseln und signieren. Zu guter Letzt wurde auch ein Einblick in Reverse Engineering
und sicheres Deployment gegeben, um fertige Anwendungen sicher bereitstellen zu können.
Das Thema wird weiterhin von Bedeutung sein, gerade weil vor kurzem wieder neue .NET Features
vorgestellt wurden: ASP.NET (ASP vNext) enthält weitere Cloud Optimierung und läuft nun neben Windows
auch auf Linux und Mac OS. Dazu könnten in weiteren Arbeiten die angebotenen Sicherheitslösungen für
Cloud Anwendungen untersucht werden. Auch die Unterstützung von Cross-Device Entwicklung wurde
weiter verbessert, wodurch der gleiche Code auf unterschiedlichen Geräten wie Phone, Tablet, Desktop
und Xbox verwendet werden kann. Dazu wäre interessant zu erforschen, inwieweit auch
Sicherheitsfeatures geräteübergreifend eingesetzt werden können.
Das .NET Framework wird sich auch in Zukunft rasant weiterentwickeln, um Entwickler bei den neuen IT
Trends zu unterstützen. Aus diesem Grund kann diese Arbeit als Grundlage für die Entwicklung von
sicheren .NET Applikationen oder weitere wissenschaftliche Arbeiten zu diesem Thema verwendet werden.
9.1.
Weitere Fehlerquellen
Trotz der vielen vorgestellten Maßnahmen kann nicht garantiert werden, dass erfolgreiche Attacken auf
eine Anwendung unmöglich sind. Durch die rasante technische Entwicklung werden täglich neue
Angriffsmöglichkeiten entdeckt, wodurch Sicherheitsmechanismen ausgehebelt werden können.
Läuft eine Webapplikation beispielsweise auf einem veralteten Webserver, so könnte ein Angreifer
Sicherheitslücken des Servers ausnutzen, um unberechtigt auf die Daten der Anwendung zuzugreifen. Aus
diesem Grund sollten Systeme wie das Betriebssystem, das Datenbanksystem oder der Webserver immer
mit den aktuellsten Sicherheitspatches vorsorgt werden. Es ist auch zu beachten, dass eine
Webanwendung mit einem eingeschränkten Benutzerkonto ausgeführt werden sollte. Dadurch kann ein
Angreifer bei einer erfolgreichen Attacke nur beschränkt Aktionen am betroffenen System ausführen.
Bei größeren Softwareprodukten werden meist auch externe Bibliotheken von unterschiedlichen
Herstellern verwendet. Diese sollten regelmäßig auf Updates geprüft werden, um Fehler und
Sicherheitslücken rasch zu beheben. Externe Bibliotheken für das .NET Framework werden häufig über
NuGet veröffentlicht, wodurch eine einfache Paketverwaltung in Visual Studio ermöglicht wird.
Zuletzt muss noch gesagt werden, dass menschliche Fehler und Missbräuche nicht außer Acht gelassen
werden dürfen. Es kommt immer wieder vor, dass vertrauliche Daten von internen Mitarbeitern an
Außenstehende weiterverkauft werden. Dadurch können Konkurrenzunternehmen oder kriminelle
Organisationen Zugriff auf geheime Daten erlangen und diese für unerwünschte Zwecke gebrauchen.
Daher sollten alle Unternehmen lückenlose Verträge besitzen, um gegen solche Verstöße rechtlich
vorgehen zu können.
68
Secure .NET Development
Literaturverzeichnis
[1 R. Siciliano, „infosec ISLAND,“ Wired Business Media, 22 April 2011. [Online]. Available:
] http://www.infosecisland.com/blogview/13075-Software-Security-Incidents-Cost-an-Average300000.html. [Zugriff am 03 April 2014].
[2 D. Rice, Geekonomics: The Real Cost of Insecure Software, Boston: Addison-Wesley Professional,
] 2008.
[3 S. Zahedani, Sichere Software mit Microsoft .NET entwickeln, Frankfurth am Main: Software & Support
] Verlag GmbH, 2007.
[4 Microsoft,
„Overview
of
the
.NET
Framework,“
] http://www.microsoft.com/net. [Zugriff am 04 04 2014].
Microsoft,
[Online].
Available:
[5 Xamarin , „mono,“ Xamarin , [Online]. Available: http://www.mono-project.com. [Zugriff am 04 04 2014].
]
[6 Microsoft Corporation, „Programmiersprachen,“ Microsoft Corporation, [Online].
] http://msdn.microsoft.com/de-de/library/aa292164(v=vs.71).aspx. [Zugriff am 7 4 2014].
Available:
[7 ITWissen,
„CTS
(common
type
system),“
ITWissen,
[Online].
Available:
] http://www.itwissen.info/definition/lexikon/CTS-common-type-system.html. [Zugriff am 8 4 2014].
[8 Microsoft Corporation, „Common Type System,“ Microsoft Corporation, [Online]. Available:
] http://msdn.microsoft.com/en-us/library/vstudio/zcx1eb1e(v=vs.100).aspx. [Zugriff am 7 4 2014].
[9 Microsoft Corporation, „.NET Framework Class Library,“ Microsoft Corporation, 12 2009. [Online].
] Available: http://msdn.microsoft.com/en-us/library/vstudio/ms229335(v=vs.90).aspx. [Zugriff am 9 6
2014].
[1 W. Fischereder, „The Common Intermediate Language (CIL),“ [Online]. Available: http://www.ssw.uni0] linz.ac.at/Teaching/Lectures/Sem/2003/reports/Fischereder/Fischereder.pdf. [Zugriff am 9 6 2014].
[1 Microsoft Corporation, „Common Language Runtime (CLR),“ Microsoft Corporation, [Online]. Available:
1] http://msdn.microsoft.com/de-de/library/8bs2ecf4(v=vs.110).aspx. [Zugriff am 9 6 2014].
[1 A. Adya, J. A. Blakeley, S. Melnik, und S. Muralidhar, „Anatomy of the ADO.NET Entity Framework,“ in
2] SIGMOD '07, Beijing, China, 2007.
[1 „ADO.NET Entity Framework Architecture,“ 9 4 2012. [Online]. Available: http://csharp3] guide.blogspot.co.at/2012/05/adonet-entity-framework-architecture.html. [Zugriff am 9 04 2014].
[1 P. Pialorsi und M. Russo, Introducing Microsoft Linq, Redmond, WA, USA: Microsoft Press, 2007.
4]
[1 D. Fox, „Cross Site Scripting (XSS),“ DuD - Datenschutz und Datensicherheit, Nr. 11, 11 2012.
5]
[1 OWASP Foundation, „Cross-site Scripting (XSS),“ OWASP Foundation, 22 4 2014. [Online]. Available:
6] https://www.owasp.org/index.php/Cross-site_Scripting_(XSS). [Zugriff am 9 6 2014].
[1 OWASP Foundation, „SQL Injection,“ OWASP Foundation, 12 4 2014. [Online]. Available:
7] https://www.owasp.org/index.php/SQL_Injection. [Zugriff am 9 6 2014].
[1 Microsoft Corporation, „ADO.NET Data Providers,“ Microsoft Corporation, [Online]. Available:
8] http://msdn.microsoft.com/en-us/data/dd363565. [Zugriff am 12 6 2014].
[1 Microsoft Corporation,
„Version History,“
Microsoft Corporation,
9] http://msdn.microsoft.com/en-us/data/jj574253.aspx. [Zugriff am 12 6 2014].
[Online].
Available:
69
Secure .NET Development
[2 J. Meier, A. Mackman, B. Wastell und Prashant, „Protect From SQL Injection in ASP.NET,“ Microsoft
0] Corporation,
5
2005.
[Online].
Available:
http://msdn.microsoft.com/enus/library/ff648339.aspx#paght000002_step3. [Zugriff am 28 4 2014].
[2 OWASP Foundation, „Blind SQL Injection,“ OWASP Foundation, 26 8 2013. [Online]. Available:
1] https://www.owasp.org/index.php/Blind_SQL_Injection. [Zugriff am 3 5 2014].
[2 OWASP Foundation, „Insecure Direct Object Reference Prevention Cheat Sheet,“ OWASP
2] Foundation, 18 04 2010. [Online]. Available: https://www.owasp.org/index.php/Top_10_2007Insecure_Direct_Object_Reference. [Zugriff am 28 4 2014].
[2 E. Lippert, „GUID guide,“ Fabulous Adventures In Coding, 30 4 2012. [Online]. Available:
3] http://blogs.msdn.com/b/ericlippert/archive/2012/04/30/guid-guide-part-two.aspx. [Zugriff am 28 4
2014].
[2 OWASP Foundation, „Cross-Site Request Forgery (CSRF),“ OWASP Foundation, 9 11 2013. [Online].
4] Available: https://www.owasp.org/index.php/CSRF. [Zugriff am 20 4 2014].
[2 W. Mike, „Preventing Cross-Site Request Forgery (CSRF) Attacks,“ Microsoft Corporation, 12 12 2012.
5] [Online].
Available:
http://www.asp.net/web-api/overview/security/preventing-cross-site-requestforgery-(csrf)-attacks. [Zugriff am 4 5 2014].
[2 T. Dykstra, „Creating ASP.NET Web Projects in Visual Studio 2013,“ Microsoft Corporation, 9 9 2013.
6] [Online]. Available: http://www.asp.net/visual-studio/overview/2013/creating-web-projects-in-visualstudio#auth. [Zugriff am 15 5 2014].
[2 H. Sun, „Understanding OWIN Forms authentication in MVC 5,“ Microsoft Corporation, 3 7 2013.
7] [Online]. Available: http://blogs.msdn.com/b/webdev/archive/2013/07/03/understanding-owin-formsauthentication-in-mvc-5.aspx. [Zugriff am 5 5 2014].
[2 Microsoft Corporation, „ASP.NET Web API,“ Microsoft Corporation, [Online].
8] http://msdn.microsoft.com/en-us/library/hh833994(v=vs.108).aspx. [Zugriff am 9 6 2014].
Available:
[2 M. Cretzman und T. Weeks, „Best Practices for Preventing DoS/Denial of Service Attacks,“ Microsoft
9] Corporation, [Online]. Available: http://technet.microsoft.com/en-us/library/cc750213.aspx. [Zugriff am
12 6 2014].
[3 Microsoft Corporation, „Open Data Protocol,“
0] http://www.odata.org/. [Zugriff am 5 5 2014].
Microsoft
Corporation,
[Online].
Available:
[3 H. Ge, „Protect your Queryable API with the validation feature in ASP.NET Web API OData,“ Microsoft
1] Corporation,
6
2
2013.
[Online].
Available:
http://blogs.msdn.com/b/webdev/archive/2013/02/06/protect-your-queryable-api-with-validationfeature-in-asp-net-web-api-odata.aspx. [Zugriff am 12 6 2014].
[3 J. Liberty und H. Alex, Programming .NET 3.5, Sebastopol: O'Reilly Media, Inc, 2008.
2]
[3 D. Chappell, „Introducing Windows Communication Foundation,“ 1 2010. [Online]. Available:
3] http://download.microsoft.com/download/C/2/5/C2549372-D37D-4F55-939A74F1790D4963/Introducing_WCF_in_NET_Framework_4.pdf. [Zugriff am 12 5 2014].
[3 Microsoft Corporation, „WCF Essentials: Contracts,“ Microsoft Corporation, [Online]. Available:
4] http://msdn.microsoft.com/en-us/library/ff183866.aspx. [Zugriff am 12 6 2014].
[3 Microsoft Corporation, „How to: Use a Custom User Name and Password Validator,“ Microsoft
5] Corporation, [Online]. Available: http://msdn.microsoft.com/en-us/library/aa702565(v=vs.110).aspx.
[Zugriff am 12 6 2014].
[3 Microsoft Corporation, „How to: Use the ASP.NET Membership Provider,“ Microsoft Corporation,
6] [Online]. Available: http://msdn.microsoft.com/en-us/library/ms731049(v=vs.110).aspx. [Zugriff am 12
6 2014].
70
Secure .NET Development
[3 Microsoft Corporation, „WCF and ASP.NET Web API,“ Microsoft Corporation, [Online]. Available:
7] http://msdn.microsoft.com/en-us/library/jj823172(v=vs.110).aspx. [Zugriff am 13 5 2014].
[3 Network Associates International BV., „Einführung in die Kryptographie,“ 24 12 1999. [Online].
8] Available: ftp://ftp.pgpi.org/pub/pgp/6.5/docs/german/IntroToCrypto.pdf. [Zugriff am 6 5 2014].
[3 A. Beutelspacher, J. Schwenk und K.-D. Wolfenstetter, Moderne Verfahren der Kryptographie,
9] Wiesbaden: Vieweg+Teubner Verlag | Springer Fachmedien Wiesbaden GmbH 2010 , 2010.
[4 Microsoft Corporation, „ECDiffieHellmanCng Class,“ Microsoft Corporation, [Online]. Available:
0] http://msdn.microsoft.com/en-us/library/system.security.cryptography.ecdiffiehellmancng.aspx. [Zugriff
am 08 05 2014].
[4 Bundesamt für Sicherheit in der Informationstechnik, „Asymmetrische Verschlüsselung,“ Bundesamt
1] für
Sicherheit
in
der
Informationstechnik,
[Online].
Available:
https://www.bsi-fuerbuerger.de/BSIFB/DE/SicherheitImNetz/Verschluesseltkommunizieren/Grundlagenwissen/Asymmetri
scheVerschluesselung/asymmetrische_verschluesselung_node.html. [Zugriff am 12 6 2014].
[4 F. Bourseau und D. Fox, „Vorzüge und Grenzen des RSA-Verfahrens,“ Datenschutz und
2] Datensicherheit, pp. 84-89, 2002.
[4 GlobalSign, „PersonalSign-Zertifikate,“ GlobalSign, [Online]. Available: https://www.globalsign.com/de3] de/personalsign/. [Zugriff am 9 6 2014].
[4 K. K. Panday , „Various SSL/TLS Certificate File Types/Extensions,“ Microsoft Corporation, 4 11 2010.
4] [Online]. Available: http://blogs.msdn.com/b/kaushal/archive/2010/11/05/ssl-certificates.aspx. [Zugriff
am 12 6 2014].
[4 D. Baier, „Unterstützen von Zertifikaten in Anwendungen mit .NET Framework 2.0,“ 3 2007. [Online].
5] Available: http://msdn.microsoft.com/de-de/magazine/cc163454.aspx. [Zugriff am 10 5 2014].
[4 S. Tahiri, „Demystifying Dot NET Reverse Engineering,“ 24 10 2012. [Online]. Available:
6] http://resources.infosecinstitute.com/demystifying-dot-net-reverse-engineering-part-1-bigintroduction/. [Zugriff am 9 6 2014].
[4 T. Patton, „Reverse engineering your .NET applications,“ 17 5 2013. [Online]. Available:
7] http://www.techrepublic.com/blog/software-engineer/reverse-engineering-your-net-applications/.
[Zugriff am 12 6 2014].
[4 G. Torok und B. Leach, „Thwart Reverse Engineering of Your Visual Basic .NET or C# Code,“ Microsoft
8] Corporation,
12
2003.
[Online].
Available:
http://msdn.microsoft.com/enus/magazine/cc164058.aspx#S3. [Zugriff am 12 6 2014].
[4 LogicNP Software, „8 Ways To Protect And Obfuscate Your .Net Code Against Reverse-Engineering
9] Using
Crypto
Obfuscator,“
LogicNP
Software,
[Online].
Available:
http://www.ssware.com/articles/protect-and-obfuscate-your-dotnet-code-against-reverse-engineeringusing-crypto-obfuscator.htm. [Zugriff am 12 6 2014].
[5 Microsoft Corporation, „Overview of Protected Configuration,“ Microsoft Corporation, [Online].
0] Available: http://msdn.microsoft.com/en-us/library/hh8x3tas(v=vs.100).aspx. [Zugriff am 12 6 2014].
[5 Microsoft Corporation, „Encrypting Configuration Information Using Protected Configuration,“ Microsoft
1] Corporation, [Online]. Available: http://msdn.microsoft.com/en-us/library/53tyfkaw(v=vs.100).aspx.
[Zugriff am 17 5 2014].
[5 J.
Roberts,
„Protected
Configuration,“
Blayd
Software,
2] http://www.blayd.co.uk/article.aspx?pageid=1012. [Zugriff am 12 6 2014].
[Online].
Available:
[5 Microsoft Corporation, „Importing and Exporting Protected Configuration RSA Key Containers,“
3] Microsoft
Corporation,
[Online].
Available:
http://msdn.microsoft.com/enus/library/yxw286t2(v=vs.100).aspx. [Zugriff am 12 6 2014].
[5 Microsoft Corporation, „Strong-Named Assemblies,“ Microsoft Corporation, [Online]. Available:
4] http://msdn.microsoft.com/en-us/library/wd40t7ad(v=vs.110).aspx. [Zugriff am 12 6 2014].
71
Secure .NET Development
[5 Microsoft Corporation, „Signierung mit starken Namen für verwaltete Anwendungen,“ Microsoft
5] Corporation,
11
2007.
[Online].
Available:
http://msdn.microsoft.com/dede/library/h4fa028b(v=vs.90).aspx. [Zugriff am 19 5 2014].
[5 Microsoft Corporation, „Übersicht über die ClickOnce-Bereitstellung,“ Microsoft Corporation, 11 2007.
6] [Online]. Available: http://msdn.microsoft.com/de-de/library/142dbbz4(v=vs.90).aspx. [Zugriff am 19 5
2014].
[5 S. Sanderson, „Prevent Cross-Site Request Forgery (CSRF) using ASP.NET MVC’s
7] AntiForgeryToken()
helper,“
1
9
2008.
[Online].
Available:
http://blog.stevensanderson.com/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnetmvcs-antiforgerytoken-helper/. [Zugriff am 4 5 2014].
[5 S. Hongye, „Understanding OWIN Forms authentication in MVC 5,“ Microsoft Corporation, 7 3 2013.
8] [Online]. Available: http://blogs.msdn.com/b/webdev/archive/2013/07/03/understanding-owin-formsauthentication-in-mvc-5.aspx. [Zugriff am 28 05 2014].
[5 V. Raja und K. J. Fernandes, Reverse Engineering - An Industrial Perspective, London: Springer
9] Verlag, 2008.
72
Herunterladen