Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs
ASP German Homepage Homepage
 

Liste

.NET 2.0 (1)
.NET Allgemein (16)
.NET Fu (5)
ADO.NET (11)
Aprilscherz (3)
ASP Grundlagen (44)
ASP Tricks (83)
ASP.NET (44)
ASPIntranet.de (5)
C# (28)
Datenbank (44)
Dokumentation (4)
IIS 6.0 (1)
Komponenten (29)
Optimierung (10)
Server (21)
Sicherheit (34)
Tee Off (6)
VB.NET (6)
WAP (8)
Web Services (11)
XML (9)

RSS 2.0 - Die neuesten fünf Artikel auf AspHeute.com


 

Suchen





 

English Articles
Chinese Articles
Unsere Autoren
 
Link zu AspHeute
Impressum
Werben
Anfragen

Streams in NTFS Dateien

Geschrieben von: Christoph Wille
Kategorie: ASP Tricks

Im heutigen Artikel möchte ich etwas in die Untiefen von NTFS (NT File System) abtauchen, und ein interessantes Feature besprechen: Streams. Zuerst werde ich mich mit den Grundlagen beschäftigen, und dann Beispiele bringen, wie man in Streams schreibt, und Daten aus Streams ausliest. Das Schöne ist, daß man keinerlei zusätzliche Komponenten braucht, um dieses Feature des Betriebssystems zu seinen Gunsten zu verwenden.

Streams - die Grundlagen

Was sind Streams? Vereinfacht gesagt kann eine Datei auf einer NTFS Partition in mehrere "Unterbereiche" (Streams) aufgeteilt werden, die separat ansprechbar sind - wobei allerdings nur einer davon standardmäßig sichtbar (=lesbar) ist - der unbenannte Standardstream. Das folgende Bild zeigt schematisch eine Datei und ihre Streams.

Wie bereits erwähnt muß nur der Standardstream existieren, alle weiteren Streams sind optional. Der Zugriff via zB FileSystemObject auf den Standardstream erfolgt einfach über den Dateinamen: myfile.ext. Bei Streams stellt sich nur eine kleine Änderung ein: myfile.ext:streamname. An den eigentlichen Dateinamen wird mit Doppelpunkt der Streamname angehängt.

Die Daten des jeweiligen Streams werden intern vom Betriebssystem wie folgt angesprochen:

myfile.ext:mystream:$DATA

Ich hoffe, mit dem $DATA habe ich jetzt bei einigen Herrschaften eine Glocke geläutet - es gab bei IIS mit ASP den sogenannten ::$DATA Bug, der es erlaubte, an der ASP Engine vorbei den Sourcecode einer ASP Datei downzuloaden - und zwar genau über das Standardstreamfeature von NTFS, das von IIS nicht korrekt abgeblockt wurde.

Weil wir gerade beim Thema Sicherheit sind: wofür soll denn nun für einen ASP Programmierer das Streams Feature von Nutzen sein? Nun, wenn nur der Standardstream sichtbar ist, heißt das, daß ich sensitive Informationen in weiteren Streams ablegen kann. Und das Beste ist, daß weder über FTP, einen Web Browser und festhalten - noch über den Windows Explorer - diese Streams sichtbar werden! Wer also bestimmte Daten nicht nur vor Hackern sondern auch vor seinem Provider verstecken will, der liegt mit Streams genau richtig.

Ein weiteres Anwendungsgebiet von Streams wäre zum Beispiel, daß man eine Datei für Lesen und Schreiben gleichzeitig aufmachen kann - das Locking funktioniert per Stream. Anwendung könnte das für Datei-basierte Foren und so weiter finden.

Da wir nun die Anwendungsgebiete im Groben mal abgesteckt haben, kommen wir zu einem wichtigen Punkt der impliziert ist, aber auch explizit erwähnt werden sollte: das Streams Feature ist nur auf NTFS vorhanden ist (ergo Windows NT/2000). Will man eine Datei, die mehrere Streams enthält, auf eine andere Partition kopieren (FAT, FAT32), so werden die zusätzlichen Streams nicht mitgenommen - man wird allerdings davor gewarnt:

Aus diesem Grund sollte man sich rückversichern, daß die aktuelle Partition Streams unterstützt - möglichst bevor man Streams herumspielt. Die folgende Funktion ist Teil der Datei StreamLibrary.asp, die als Include in allen anderen Beispielen verwendet wird (auch Teil des Downloads).

Function IsDriveNTFSDrive(strDriveLetter)
  Dim fsObj, drvObj, strTypeOfFS
  IsDriveNTFSDrive = False
  
  Set fsObj = CreateObject("Scripting.FileSystemObject")
  Set drvObj = fsObj.GetDrive(strDriveLetter)
  strTypeOfFS = drvObj.FileSystem
  
  If (0 = StrComp("NTFS", strTypeOfFS)) Then
    IsDriveNTFSDrive = True
  End If
End Function

Diese Funktion verwendet die FileSystem Eigenschaft des Drive Objekts um den Typ des Dateisystems zu ermitteln. Bei NTFS liefert sie True, ansonsten immer False.

Schreiben von Streams

Die Voraussetzungen sind abgeklärt, jetzt geht es um's Schreiben in die Datei. Dazu habe ich auch eine universell einsetzbare Funktion gebaut: WriteStreamData.

Sub WriteStreamData(strTargetFile, strTargetStream, strStreamData)
  Dim fsObj, objTextStream, strFullStreamedName
  
  Set fsObj = CreateObject("Scripting.FileSystemObject")
  
  ' der default stream muß zwar nicht explizit generiert werden, es 
  ' empfiehlt sich aber sehr!
  If (Not fsObj.FileExists(strTargetFile)) Then
    Set objTextStream = fsObj.CreateTextFile(strTargetFile)
    objTextStream.Write "Mehrfach-Stream Datei"
    objTextStream.Close
    Set objTextStream = Nothing
  End If
  
  strFullStreamedName = strTargetFile & ":" & strTargetStream
  Set objTextStream = fsObj.CreateTextFile(strFullStreamedName)
  objTextStream.Write strStreamData
  objTextStream.Close
  
  Set objTextStream = Nothing
  Set fsObj = Nothing
End Sub

Etwas, das ich nicht tun müßte, ist den Standardstream mit Daten anzufüllen - es dient nur dazu, daß die Datei nicht 0 Byte lang ist. Der Grund warum sie 0 Byte wäre ist der, daß nur der Standardstream zur Größenkalkulation herangezogen werden kann (also wer seinem Systemadministrator ein Ei legen will, der kann mehrere MB's in Dateien der Länge 0 verstecken...). Auch wenn die Größe vom Standardstream gerechnet wird, werden alle Streams bei einem Backup gesichert - also um die Daten in den zusätzlichen Streams muß man sich nicht fürchten.

Das eigentliche Schreiben in einen Stream ist sehr simpel - nur 4 Zeilen inklusive des Erstellens eines Strings mit dem Streamnamen und dem Schließen der Datei. Schon hat man Daten erfolgreich versteckt.

Verwendet wird die Funktion wie folgt (WriteStream.asp):

<!--#include file="StreamLibrary.asp"-->
<%
Dim strFile, strStream
strFile = Server.MapPath("demo.txt")
strStream = "mystream"

If IsDriveNTFSDrive("d") Then
  WriteStreamData strFile, strStream, "some data you won't see on disk"
End If
%>

Das Beispiel ist wirklich sehr straight-forward: die Datei wird definiert, das Dateisystem auf NTFS gecheckt, und dann die Daten geschrieben. Sollte alles gutgehen, bekommt man eine leere Seite präsentiert (das sollte man unter Umständen ändern), sonst eine Fehlermeldung.

Wer möchte, kann die Datei nun in Notepad öffnen - er wird nur den Standardtext aus der Funktion WriteStreamData erhalten. Um die Daten des zusätzlichen Streams zu sehen, muß man mit Doppelpunkt hinter dem Dateinamen den Streamnamen angeben, und schon sieht man die Daten auch in Notepad - aber wie gesagt, man muß den Namen des Streams kennen.

Lesen von Streams

Da unsere Daten nun sicher in einem Stream liegen, stellt sich noch die Frage, wie man sie wieder auslesen kann. Diese Frage beantwortet der Sourcecode zur Funktion ReadStreamData:

Function ReadStreamData(strFileName, strStreamName)
  Dim fsObj, objTextStream, strContent
  Set fsObj = CreateObject("Scripting.FileSystemObject")
  
  If Not fsObj.FileExists(strFileName) Then
    Err.Raise vbObjectError+1, "Datei existiert nicht!"
  End If
  
  Set objTextStream = fsObj.OpenTextFile(strFileName & ":" & strStreamName)
  strContent = objTextStream.ReadAll()
  objTextStream.Close
  Set objTextStream = Nothing
  Set fsObj = Nothing
  
  ReadStreamData = strContent
End Function

Wieder passiert hier eigentlich nichts aufregendes - ich habe nur eine kleine Sicherheitsmaßnahme eingebaut: das Checken, ob die Datei existiert. Allerdings kümmere ich mich nicht um die Fehler, die entstehen falls der Stream nicht existiert - das ist Aufgabe des Lesers!

Anwendung findet die Funktion in der Datei ReadStreams.asp:

<!--#include file="StreamLibrary.asp"-->
<%
Dim strFile, strStream
strFile = Server.MapPath("demo.txt")
strStream = "mystream"

If IsDriveNTFSDrive("d") Then
  Response.Write ReadStreamData(strFile, strStream)
End If
%>

Das Lesen funktioniert im Grunde genauso einfach wie das Schreiben.

Mit der Library die ich Ihnen in diesem Artikel vorgestellt habe, kann man bequem mit Streams arbeiten - und diese zum "Verstecken" von Daten oder zum Speichern von verwandten Daten in einer einzigen Datei verwenden.

Schlußbemerkung

Wichtig zu bemerken ist unbedingt, daß man mit dem FileSystemObject keine Möglichkeit hat, alle Streams, die in einer Datei vorhanden sind, einfach aufzulisten. Man muß wissen, daß ein Stream existiert (auch nicht schlecht von der Perspektive der Sicherheit). Wer allerdings einen C++ Compiler hat, der kann mit WIN32 API Funktionen sehr wohl alle Streams auflisten und anzeigen lassen - also 100% sicher sind die Daten nicht, das würde nur mit Verschlüsselung stimmen (wenn sie richtig angewendet ist).

Download des Codes

Klicken Sie hier, um den Download zu starten.

Verwandte Artikel

Dateiattribute unter ASP auslesen
Lesen von Textdateien
Minigolf - 99 Bottles of Beer

Links zu anderen Sites

File Access Issue with Windows NT Internet Information Server ($DATA Bug)

Wenn Sie jetzt Fragen haben...

Wenn Sie Fragen rund um die in diesem Artikel vorgestellte Technologie haben, dann schauen Sie einfach bei uns in den Community Foren der deutschen .NET Community vorbei. Die Teilnehmer helfen Ihnen gerne, wenn Sie sich zur im Artikel vorgestellten Technologie weiterbilden möchten.

Haben Sie Fragen die sich direkt auf den Inhalt des Artikels beziehen, dann schreiben Sie dem Autor! Unsere Autoren freuen sich über Feedback zu ihren Artikeln. Ein einfacher Klick auf die Autor kontaktieren Schaltfläche (weiter unten) und schon haben Sie ein für diesen Artikel personalisiertes Anfrageformular.

 

Und zu guter Letzt möchten wir Sie bitten, den Artikel zu bewerten. Damit helfen Sie uns, die Qualität der Artikel zu verbessern - und anderen Lesern bei der Auswahl der Artikel, die sie lesen sollten.

Bewerten Sie diesen Artikel
 Sehr gut   Nicht genügend  
   1  2  3  4  5  
 

  
   Für Ausdruck optimierte Seite

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.