Mittwoch, 23. Februar 2011

PHP Includes absichern

Über die Absicherung von PHP include()s wurde bereits viel geschrieben. Hier kommt eine kurze Zusammenfassung sowie ein Zusatzhinweis, wie ich meine Webseite absichere.

(Date/Datum: 080303-15:08, Hits: 6837)

PHP ist, auch wenn sie als nicht sonderlich sicher und zudem langsam als gilt, eine sehr populäre Skriptsprache im Bereich der Webprogrammierung.

Eine der wichtigsten Techniken für PHP ist dabei das dynamische Nachladen von Seiteninhalten mittels der include()-Anweisung. Damit ein PHP-Skript dann auch weiß, was es in die aktuelle Seite laden soll, wird meist ein Dateiname oder ein bestimmter Code als Variable übergeben. Etwa in der Form http://doomed-reality.org/index.php?sub=steffen.

Nur ganz unerfahrene Entwickler machen sich hierbei nicht die Mühe, die übergebenen Werte zu überprüfen, was besonders in der Vergangenheit, als es noch kein so großes Bewußtsein für Web-Sicherheit gab, zu einer sehr simplen Form von Angriffen führte. Dabei versuchte man etwa die passwd-Datei mittels ?sub=/etc/passwd zu laden um sich so eine Übersicht über die Accounts des Systems zu verschaffen und eventuell einen Remote-Login auf dem Webserver zu bekommen.

Absicherung

Die Absicherung ist einfach (und wurde von mir im Praxisbuch Netzwerksicherheit beschrieben): Man definiert einfach alle gültigen Werte und lässt nur diese zu. Dies lässt sich mit if-Abfragen und switch-Anweisungen am einfachsten erledigen.

if ($_GET["sub"] == "ABC")
include("ABC.xyz");
else if ($_GET["sub"] == "XYZ")
include("XYZ.xyz");
else
include("START.xyz");

Auf dieser Webseite habe ich es mir noch etwas einfacher gemacht und alle gültigen Werte in ein Array gesteckt. Ist der Wert der Variable gleich eines Wertes im Array, so wird die Seite eingebunden. Andernfalls nicht.

Verstecken von Include-Dateien

Was hingegen weniger häufig anzutreffen ist, ist das die Dateien, die eingebunden werden, auch versteckt werden. Zugegebener Maßen ... dies habe auch ich lange Zeit nicht beherzigt. Bei einem Angriff versucht der Angreifer dann an den Quellcode einer Datei, die eingebunden wird, zu kommen.

Nehmen wir wieder das Beispiel vom Anfang. Es wird ein GET-Request auf http://wendzel.de/index.php?sub=steffen ausgeführt. Dann könnte der Angreifer davon ausgehen, dass sich im Dateinamen der einzubindenden Datei das Wort "steffen" befindet. Nun könnte er versuchen, die Datei durch einen direkten Request zu entdecken. Hier ein paar Beispiele, die ein Angreifer wohl ausprobieren wird:

steffen.sub
steffen
steffen_sub
steffen.inc
steffen_inc
inc.steffen
steffen.txt
steffen.php
steffen.php3
...

Vielleicht denkt der Angreifer auch an Unterverzeichnisse, und probiert nun auch solche Dateinamen aus:

inc/steffen.sub
sub/steffen.sub
subs/steffen.sub
inc/steffen.inc
...

Mit kleinen (und zudem nicht aufwändigen) Skripten lassen sich solche Angreife leicht automatisieren.

Auch hier gibt es Gegenmaßnahmen

Erschweren kann man dem Angreifer seine Tätigkeit aber mit sehr einfachen Mitteln: Beispielsweise könnte man sonderbare Dateinamen verwenden (etwa GE203fgn2-steffen-23490gt) oder könnte aus Kleinbuchstaben Großbuchstaben machen (und umgedreht).

Am einfachsten und besten finde ich aber die Methode, die ich auch hier anwende: Die Dateien werden aus einem .htaccess-Geschützten Unterverzeichnis geladen (und sind natürlich zusätzlich mit einer Modifikation im Dateinamen versehen). So müsste ein Angreifer Benutzer und Passwort, das Unterverzeichnis selbst und die Modifikation der Dateinamen erraten (eine leere index.html-Datei schützt die Dateinamen im Verzeichnis -- alternativ könnte man aber auch Directory Listings deaktivieren).

KOMMENTARE AUS DEM ARCHIV:

Kommentare:

Von: just me
Hallo,
es ist doch aber so, auch wenn der Angreifer an eine Datei steffen.php3 heran käme, so würde er von der Datei ja nicht den Source Code bekommen, so lange es sich bei dem Inhalt um PHP handelt? Oder sehe ich da etwas falsch? Der Server, sofern php installiert und lauffähig ist, "compiliert" doch den Code bevor dieser verschickt wird.
Gruß

____
Von: Steffen Wendzel
An den Code einer .php-Datei kommt der Angreifer nur bei einer Fehlkonfiguration des Servers. Wenn man aber keine php-Dateien einbindet, sondern Dateien mit einer anderen Endung, dann können diese direkt mit Quellcode abgeholt werden. Man kann natürlich auch direkt .php-Dateien einbinden, das wäre auch nicht soooo unsicher. Doch dann sollte man unbedingt darauf aufpassen, dass diese Dateien nicht ohne die einbindende index.php-Datei für Angriffe ausgenutzt werden können! (bspw. Überschreiben von irgendwelchen Variablen, die sonst die index.php setzen würde etc.)
____
Von: just me 2
Hallo,
was wäre den eine schnelle UND sichere Sprache für das WWW?

Gruß

____
Von: Steffen Wendzel
Hi justme2!

Die Sicherheit kommt primär auf dich an (eine sichere Sprachimplementierung sei mal gegeben). Mit PHP (das ja des öfteren bzgl. seiner Sicherheit in der Kritik stand) habe ich in den letzen 1,5 Jahren eine große Seite (noch immer nicht online) aufgebaut und bin mit der Performance (die aber primär auf die -- leider riesige -- Datenbank geht) nicht ganz zufrieden. Ich werde wohl für das nächste Projekt Perl/Mason (www.masonhq.com) ausprobieren, das für Highperformance-Seiten ausgelegt ist (Amazon benutzt das angeblich auch).

Die Performance kommt zudem auf deine Programmierkenntnisse an. Du kannst auch eine Webseite in C programmieren, die langsam ist (wobei ein optimiertes und super implementiertes C-Programm praktisch immer das schnellste sein wird, was du kriegen kannst!). Wenn Du aber die Möglichkeiten der Sprache (speziell C) kennst und weißt, welche Algorithmen/abstrakte Datentypen zur Lösung von Aufgabe X am schnellsten sind, dann hast du eben gewonnen.

Eine andere Problematik besteht darin, eine relativ schnelle Sprache (etwa Perl, Python) zu verwenden und dann ein "tolles", aber aufgeblasenes Web-Framework zu nutzen, was dir die Performance wieder klaut.

Trotzdem (und zurück zum Thema Sicherheit): Wenn Du nicht über die webbasierten Angriffsarten informiert bist, dann hast du schon verloren.

Apropos, Johannes und ich halten im Juni wahrscheinlich einen Workshop zum Thema Linux- und Websicherheit ab, da kannst Du dann mehr über die Sicherheit von Web-Anwendungen erfahren.

Steffen

____
Von: fip25
Ich mache das so, die z.B. index.php Datei mit den Includes definiert eine Konstante z.B.
define( HAUPTSEITEGELADEN , true);


Alle Includes haben auf den ersten Zeilen dies:
if (!defined( HAUPTSEITEGELADEN ))
{
exit;
}

Funktioniert prächtig!

____
Von: Steffen
Hi fip25,

das hört sich nach einer guten Idee an. Allerdings unter der Bedingung, dass die Dateien die Endung .php kriegen, damit sie nicht direkt aufgerufen werden können. Andernfalls würde ich die Include-Dateien in jedem Fall trotzdem verstecken bzw. mit .htaccess-Schützen.

Steffen

____

Keine Kommentare:

Kommentar veröffentlichen