PHP-Entwickler: eure Skripte infizieren das Internet!

Hallo PHP-Entwickler!

Auch schon die eigenen PHP-Skripte der Öffentlichkeit vorgestellt? Bereits gelistet bei

  • www.php-free.de
  • www.php-resource.de
  • www.dynamic-webpages.de
  • www.skriptarchiv.com

und andere mehr? Auch herrliche Bewertungen und Kommentare bekommen? Geben tausende Downloads Grund zur Freude und erfüllen einen mit Stolz ?

Die Programmiersünden-Hölle(n)

Wie lange wird es dauern, bis eure Software hier landet:


Oh ja, die Hölle(n) aller Programmiersünden, auch der längst vergessenen. Eure ehemals ruhmreiche Software, gelistet und entlarvt als infektiöser Überträger von Würmern, Phishing-Fallen und Viren, als Wirt von Bot-Netzwerken und Spamangriffen, als Urheber von weltweiten Angriffe auf Netzwerkinfrastrukturen und Webserver. So weit ist es gekommen.

Viele Stunden Arbeit und ein Ziel vor Augen haben so manchen blind werden lassen, blind für einfachste Maßnahmen gegen den Missbrauch seiner geliebten Software. Viele von denen die daran dachten, wurden später oft schwach und erfüllten hier und da „mal schnell“ die Wünsche der Nutzer – und vergaßen dann ebenfalls Sicherungsmaßnahmen. Der große Masse allerdings war die Gefahr erst gar nicht bewusst.

Einmal in der freien Wildbahn, landete die Software auf unzählige Server und dort verlor sich ihre Spur. Tausende von Gästebücher, Abstimmungsskripte, E-Mail-Formulare, Content Mangement Systeme sind tickende Bomben auf Webserver weltweit, ihr gefährlicher Code jeder Kontrolle entzogen, schlummernd wartend, dass eine neue Welle ausgeklügelter Angriffe sie zu zombihaftem Leben erweckt…

Wer ist schuld an der Misere?

Wenn es nach mir geht:

  • Die vielen Foren sind schuld, die Codebeispiele verbreiten ohne auf die Schwachstellen einzugehen.
  • Die vielen „PHP lernen“-Webseiten sind schuld, die auf schlanke Beispiele abzielen, ohne die nötigten Sicherheitsgrundlagen zu vermitteln.
  • Die PHP-Bücher sind schuld, die in ihrer Mehrzahl bestenfalls ein Kapitel stiefmütterlich diesem Thema widmen.
  • Die Sicherheitssoftware-Hersteller sind schuld, die für die Verwendung ihrer Software Änderungen am Server, Anpassungen am Betriebssystem und Geld verlangen und so sich auf einer dieser Weisen der Masse der privaten Webanwendungen verschließen.
  • Die Sicherheitsexperten sind schuld, die lange Vorträge halten und Schriften verfassen um die Bedrohung zu erklären und damit noch mehr Material erzeugen, das sich ein Programmieranfänger nie durchlesen wird.

Und in Zukunft?

Ich entwarf im Rahmen einer wissenschaftlichen Arbeit über Sicherheitsschwachstellen in Websoftware eine Sicherheitsbibliothek, die genau diesem Missstand entgegenwirken soll. Im Gegensatz zu anderen Ansätzen, erfüllt diese Software folgende Grundvoraussetzungen für eine breite Akzeptanz:

  • Keine Änderungen an Webserver oder Betriebssystem vorausgesetzt.
  • Keine andere Software benötigt/vorausgesetzt.
  • Auch mit älteren PHP & MySQL-Versionen verwendbar.
  • Keine Domain-Konfiguration vorausgesetzt.
  • Keine Datenbank vorausgesetzt.
  • Aus wenigen Dateien bestehend.
  • Auch ohne Programmierkenntnisse verwendbar.
  • Bietet sofort signifikanten, aktiven Schutz.
  • Open-Source.

Neben diesen Grundvoraussetzungen für die Akzeptanz, gibt es noch:

  • Funktionen zur Behebung von Schwachstellen.
  • Protokollierung von Validierungen und Angriffsversuchen.
  • Konfigurierbare Maßnahmen im Angriffsfall.
  • Sicherung von Cookies.
  • Verbergen von verräterische Fehlermeldungen.

Und jetzt?

Baut in jedes kleinste Projekt und jede PHP-Webseite vom Anfang an (und auch nachträglich) die SSEQ-LIB Sicherheitsbibliothek ein. Nutzt als Erstes die simple aber wirkungsvolle Web-Firewall. Vor euer Skript gestellt sorgt sie dafür, dass unerwartete Eingabedaten gar nicht erst an etwaige Schwachstellen kommen. Sie lässt sich mit einer Liste von Variablennamen aus dem zu schützenden Skript leicht erweitern.

  1. SSEQ-LIB herunterladen
  2. Auf dem Webserver kopieren.
  3. An erster Stelle im Skript oder Webseite einbinden: include_once(’sseq-lib/seq_lib.php‘)
  4. Web-Firewall einschalten: SEQ_SANITIZE(‚id # gp # INT # 1 # 1000 # # &‘)
  5. Alle verwendeten GET/POST/COOKIE/SESSION-Variablen einpflegen.

Jetzt gibt es etwas mehr Zeit um sich mit den typischen Schwachstellen vertraut zu machen und sie in euren Skripten und Webseiten zu stopfen. Funktionen die diese Schwachstellen gezielt schließen, sind in der SSEQ-LIB Sicherheitsbibliothek bereits enthalten.

Beispiele

Was bewirkt die Einbindung von SSEQ-LIB und die Web-Firewall im Einzelnen? Um das zu demonstrieren habe ich direkt aus der Hölle der Programmiersünden und ganz aktuell einige Fälle herausgefischt:

„Maran PHP Shop“- SQL-Injection. Diese Schwachstelle hätte nicht ausgenutzt werden können, wenn im Skript die SSEQ-LIB eingebunden worden wäre.
<br />
include_once(&
#8217;sseq-lib/seq_lib.php&#8216;);<br />
SEQ_SANITIZE(&#8218;id # gp # INT # 1 # 10000 # # true  &#038;&#8216;)<br />

Der SEQ_SANITIZE-Aufruf bedeutet dabei durch die Raute (#) getrennt:

  • Prüfe die Variable „id“
  • aus GET und POST
  • auf Typ „Zahl“
  • zwischen 1
  • und 10000
  • [LEERZEICHEN] kodiere NICHT gegen Cross Site Scripting
  • „true“ maskiere Variablenwert gegen SQL-Injections

„Article Publisher Pro 1.5“ – SQL-Injection
Diese Schwachstelle hätte nicht ausgenutzt werden können, wenn im Skript die SSEQ-LIB eingebunden worden wäre:
<br />
include_once(&
#8217;sseq-lib/seq_lib.php&#8216;);<br />
SEQ_SANITIZE(&#8218;userid # gp # INT # 1 # 10000 # # true  &#038;&#8216;)<br />

Der SEQ_SANITIZE-Aufruf bedeutet dabei durch die Raute (#) getrennt:

  • Prüfe die Variable „userid“
  • aus GET und POST
  • auf Typ „Zahl“
  • zwischen 1
  • und 10000
  • [LEERZEICHEN] kodiere NICHT gegen Cross Site Scripting
  • „true“ maskiere Variablenwert gegen SQL-Injections

„Planetluc MyGallery“ – Cross Site Scripting
Diese Schwachstelle hätte nicht ausgenutzt werden können, wenn im Skript die SSEQ-LIB eingebunden worden wäre:
<br />
include_once(&
#8217;sseq-lib/seq_lib.php&#8216;);<br />
SEQ_SANITIZE(&#8218;mghash # gp # STR # 32 # 32 # true #  &#038;&#8216;)<br />

Der SEQ_SANITIZE-Aufruf bedeutet dabei durch die Raute (#) getrennt:

  • Prüfe die Variable „mghash“
  • aus GET und POST
  • auf Typ „Zeichenfolge“
  • mit Mindestlänge 32 Zeichen
  • und Maximallänge 32 Zeichen
  • Kodiere die Daten gegen Cross Site Scripting
  • [LEERZEICHEN] maskiere NICHT gegen SQL-Injections

Das könnte dich auch interessieren …

7 Antworten

  1. Roger sagt:

    Hallo

    Mal ne Frage.
    Ich mach das immer so, wenn ich einen INT
    erwarte:

    $id = (int) htmlspecialchars($_GET[‚id‘]);

    Ist das ok? Oder gibt es ein Problem damit?

  2. Erich Kachel sagt:

    Das sollte bereits ausreichen: $id = (int)$_GET[‚id‘]; Da gehen nur Zahlen durch. Wenn man mit diesen Zahlen später rechnet (z.B. beim ausrechnen der Seitenzahlen o.ä.) sollte auch auf den Zahlenbereich geachtet werden. Die Eingabe übergroßer oder negativer Zahlen sollte nicht mit einem PHP-Fehler enden ;)

  3. Roger sagt:

    Ja, danke :)

    Jetzt ist mir auch aufgefallen, dass es htmlspecialchars() gar nicht mehr braucht.

    Gut. Meistens steht sowieso eine Klasse dahinter.
    will ich beispielsweise die Daten von Adresse 99 aus
    aus der DB holen, kommt sowieso meist folgendes zum
    Einsatz:

    $kunde = new Kunde;
    if($kunde->loadByID((int) $_GET[‚id‘]))
    {
    // Zeige die Daten…
    }
    else
    {
    // Gib Meldung aus, dass nix ist…
    }

    Somit hoffe ich, dass kein Hacker den GET-Parameter
    verändern kann, um Schaden anzurichten. Ich habe mir
    gedacht, dass wenn ich $_GET[‚id‘] einfach so
    übernehme, hier also 99 erwarte, so könnte ein Hacker
    ja evtl. einfach ?id=99; delete * from tbl_xy ein-
    geben.
    Wenn ich es mit (int) caste, so sollte
    „?id=99; delete * from tbl_xy“ in einen int-Wert ge-
    castet werden und nichts kaputt gemacht werden können.
    Das Casten ist wahrscheinlich nicht so performant,
    aber ich finde es geht dennoch schnell. Zumindest
    für das „sichere“ Handling von erwarteten Zahlen
    finde ich das Casten sinnvoll.
    Für Abfragen in der DB brauche ich meistens eh nur
    die ID, also nummerische Werte. Gebe ich Strings
    mit GET/POST mit, so hoffe ich, dass diese mit
    htmlspecialchars() Web-sicher gehandelt werden.

    Viel mehr wundert es mich, dass sehr viele Web-Entwickler
    die Grafiken im selben inc-Verzeichnis ablegen, wie
    Code der Applikation ist; ein Hacker braucht ja nur
    mit der r.Maustaste auf die Grafik zu klicken und
    schon sieht er: „aha, inc/images/…. Da muss es doch
    auch ein inc/classes/ etc. geben. Mal schauen, ob ich
    da ein paar xy.inc finde“.

    Ich mache es meist so, dass ich ein
    ./public/css
    ./public/images
    ./public/download
    habe, wo sich der Hacker tummeln kann.

    Den Programmcode der Applikation lege ich nicht ins
    ./inc/…
    sondern in ein nur mir bekannten Ordner ab, der
    (hoffentlich) nicht so schnell vom Hacker erraten
    wird.

    LG Roger

  4. Erich Kachel sagt:

    „Das Casten ist wahrscheinlich nicht so performant[…]“

    Ich ziehe die Sicherheit des Systems und der Daten der Performanz immer vor.

    Was die Position von Programmcode betrifft ist – wenn möglich – immer eine Position außerhalb des „htdocs“ oder „public“-Verzeichnisses zu wählen, also außerhalb des Zugriffs des Webservers.

    Wenn das nicht geht muss man hoffen, dass der Webserver „directory listing“ abgeschaltet hat oder dass auch „.inc“-Dateien dem PHP-Parser überreicht werden und nicht als „plain text“ ausgegeben werden.

  5. stefan brinkmann sagt:


    global $_SEQ_SESSIONLIFETIME,

    Hahahahahaha
    Ich lach mich tot!
    Empfindliche Steuerdaten liegen offen im Code rum.
    Die allerschlimmsten Anfängerfehler als security code verkauft.

    Also wenn schon, dann bitte mit define(‚_SEQ_SESSIONLIFETIME‘, …).
    Wenn ich so was sehe, brauche ich mir den Rest garnicht mehr anschauen…

  6. Erich Kachel sagt:

    Hallo Stefan,

    danke für den guten Tipp! Alles bringt das Projekt weiter und es ist mir so lieber, als wenn keine Kritik kommt.

    Grüße
    Erich

  1. 10. November 2008

    […] wenn man Eric Kachel und seinem Blog glaubt. In für meinen Geschmack leicht marktschreierischer Weise macht Eric auf die am häufigsten […]