Sicheres PHP

Fragen zum Thema HTML, JavaScript, PHP
Benutzeravatar
Jside
Beiträge: 377
Registriert: Di Nov 11, 2008 12:56 am

Sicheres PHP

Beitrag von Jside » Do Jan 01, 2009 9:59 am

Mal eine Frage, wie kann ich "sicher" PHP Scripten?

Also da PHP ja Serverseitig läuft, kann man PHP ja eigentlich nur beim übertragen von z.b. Variablen attackieren. Also z.b.:

irgendwas.html

Code: Alles auswählen

 <form method="post" action="blabla.php"><input type="text" name="Fname">
blabla.php

Code: Alles auswählen

<?php
    $name1 = $_POST['Fname'];
echo $name1;
?>
Könnte ich ja einfach durch Betrachten des HTML Codex und
umgehen, aber wie kann ich sowas verhindern? ...wenn überhaupt?
Worauf muss ich noch achten?
Ist es z.b. sehr sicher, überhauptkeine oder wenig externe Variablen in das script zu lassen? Oder ist das von anderen Faktoren abhängig?
Wie sieht das z.b. aus, wenn ich ein Script, andass ich Variablen übergeben will einen chmod, der nur den PHP und Apache(mal vom root abgesehen) Gruppe erlaubt diese zu lesen ist das dann mit der Variablenübergabe halbwegs sicher?
Wo sind andere (Serverseitge) Schwachstellen von PHP?
php --version
PHP 5.2.6 with Suhosin-Patch 0.9.6.2 (cli) (built: Nov 14 2008 16:48:49)
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies
(mit apache 2)

Ich will nämlich, sobald ich ein anständiges-nicht-aus-sperrmüll-gebautes (Server)Rack habe meinen 1He Server(IBM xSeries 330, 500MB RAM) 24/7 als Privater Webserver betreiben und bastle gerade eine CMS

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3123
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Sicheres PHP

Beitrag von cloidnerux » Do Jan 01, 2009 11:23 am

Also PHP ist relativ sicher.
Wenn du Variablen über POST übergibts, dann werden sie nihct in der Adresse angezeigt.
Wenn du Variablen über GET übergibst werden sie in der Adressleite angezeigt.
Variablen, die der Lokale Computer übergibt müssen nihct sicher sein, da ein Angreifer die Richtigkeit nicht überprüfen kann => Passworteingabe.
Weiterhin kanst du Passwörter dierekt als md5-String speichern. So kann kein Angreifer etwas herausfinden.
Mit Sessions kannst du Variablen ohne POST oder GET übergeben. Eine Session ist mit einem 128-Bit Schlüsel geschützt.
Wenn mans also Richtig macht, ist PHP sehr sicher.
Redundanz macht wiederholen unnötig.
quod erat expectandum

Benutzeravatar
Dubbel
Beiträge: 197
Registriert: So Jul 06, 2008 6:25 pm
Wohnort: Kopenhagen
Kontaktdaten:

Re: Sicheres PHP

Beitrag von Dubbel » Do Jan 01, 2009 6:16 pm

Man kann natürlich alle Arten von Kommunikation zwischen Server und Client abfangen. Auch POST-Daten kann man bequem z.B. mit dem Firefox-Plugin TamperData (mit dem man auch in 95% aller Flash-Highscore-Games plötzlich auf Platz 1 ist) verändern.
Könnte ich ja einfach durch Betrachten des HTML Codex und http://www.irgendwas.de/blabla.php?Fname='ein böser text' umgehen, aber wie kann ich sowas verhindern? ...wenn überhaupt?
Soweit ich weiß, bringt es nichts den Wert der Variable in dem GET-Array zu ändern (was ja durch ?name=bla geschehen würde), weil du ja in deinem PHP-Code nur das POST-Array ausliest - aber wie oben geschrieben: Durch ein Plugin kann man POST Daten trotzdem verändern, deshalb immer überprüfen, ob die Daten Sinn machen ("Warum ist in der ID ein Buchstabe vorhanden?", etc.).

Wenn man die eingehenden Variablen aber überprüft (am besten macht man sich für jedes Projekt eine Funktion, die nur diese Aufgabe übernimmt), ist man schonmal gegen XSS und MySQL-Inquestions relativ gut geschützt (XSS ist natürlich auch bei Javascript ein Problem).
Wie sieht das z.b. aus, wenn ich ein Script, andass ich Variablen übergeben will einen chmod, der nur den PHP und Apache(mal vom root abgesehen) Gruppe erlaubt diese zu lesen ist das dann mit der Variablenübergabe halbwegs sicher?
Öhm, wenn ich dich richtig verstanden habe, dann würde das nichts bringen. Um die zu übertragenden Variablen zu verändern muss man ja nicht die Datei aufrufen oder gar verändern...

Benutzeravatar
Jside
Beiträge: 377
Registriert: Di Nov 11, 2008 12:56 am

Re: Sicheres PHP

Beitrag von Jside » Fr Jan 02, 2009 6:37 am

Ok, die Loginfunktion sieht so aus:

Code: Alles auswählen

 $Username = $_POST['Username'];
   $Password = $_POST['Password'];
   $Dest     = $_GET['dest'];
   if($_COOKIE["Username"]) $Username = $_COOKIE["Username"];
   if($_COOKIE["Password"]) $Password = $_COOKIE["Password"];

   if($Username != "") { //Username ist bei den Tests erstmal egal...
      if($Password == "devil") {
         if($Dest == "") { //Welche "Seite" geladen werden soll
            setCookie("Username", $Username);
            setCookie("Password", $Password);
            Printmenu();
         }
      }
Das dürfte doch sicher sein oder? Die Loginprozedur wird bei einem erfolgreichem Login in Coockies gespeichert, die beim Neuladen unabhängig wieder überprüft werden.
Oder Lohnt es sich den MD5 Hash in dem Coockie zu speichern? Oder hier generell das Passwort in MD5 hashen zu vergleichen? Denn so wie ich das sehe dürfte da daselbe herauskommen, da ja das "devil" im Server bleibt?! Die $_GET Variable stellt nur die Aktion da, die Angezeigt werden soll..

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Sicheres PHP

Beitrag von Xin » Fr Jan 02, 2009 7:31 am

Jside hat geschrieben:Ok, die Loginfunktion sieht so aus:

Code: Alles auswählen

 $Username = $_POST['Username'];[/quote]
   $Password = $_POST['Password'];
   $Dest     = $_GET['dest'];
   if($_COOKIE["Username"]) $Username = $_COOKIE["Username"];
   if($_COOKIE["Password"]) $Password = $_COOKIE["Password"];
Da gibt es array_exists, damit das sauber wird.
Außerdem sollten übergebene Werte vor gespeicherten Werten behandelt werden. Wenn der User Dir neue Werte gibt, wird er dafür einen Grund haben.
Jside hat geschrieben:Das dürfte doch sicher sein oder? Die Loginprozedur wird bei einem erfolgreichem Login in Coockies gespeichert, die beim Neuladen unabhängig wieder überprüft werden.
Klingt soweit sinnvoll.

PHP-Programme haben viele Schwachstellen, das Übertragen von "bösen" Eingaben ist da nur ein Punkt, den man in allen Sprachen beachten muss.
Sobald Du Strings bekommst, solltest Du davon ausgehen, dass diese Strings bösartig sind. Benutzer sind immer böse. Das bedeutet im Klartext, dass Du sie immer so kodieren solltest, dass sie Dir die Eingaben nichts kaputtmachen:
Jside hat geschrieben:Oder Lohnt es sich den MD5 Hash in dem Coockie zu speichern? Oder hier generell das Passwort in MD5 hashen zu vergleichen? Denn so wie ich das sehe dürfte da daselbe herauskommen, da ja das "devil" im Server bleibt?! Die $_GET Variable stellt nur die Aktion da, die Angezeigt werden soll..
...Passworter in MD5 (oder vergleichbarem) zu setzen ist hier eine Möglichkeit. Aber auch Usernamen sollten sauber kodiert sein.

Nehmen wir an, ich melde mich als User

Code: Alles auswählen

username' ); DROP TABLE Users; SELECT * FROM Somewhere WHERE ( id = '1
an und Dein CMS formt daraus eine Anfrage:

Code: Alles auswählen

SELECT password FROM users WHERE ( id = '$username' )
An die Datenbank geht:

Code: Alles auswählen

SELECT password FROM users WHERE ( id = '$username' ); DROP TABLE Users; SELECT * FROM Somewhere WHERE ( id = '1' )
Damit bin ich zwar nicht angemeldet, aber Dir fehlt auf einmal die Tabelle 'Users'...
Ich könnte mir auch einen beliebigen User anlegen - mit beliebigen Rechten...
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Jside
Beiträge: 377
Registriert: Di Nov 11, 2008 12:56 am

Re: Sicheres PHP

Beitrag von Jside » Fr Jan 02, 2009 7:59 am

Also mySQL will ich sowieso nicht unbedingt benutzten, die Passwörter/Benutzernamen sollen in einer PHP Datei als Array abgespeichert werden(dann aber als MD5)(Muss ich halt jeden Benutzter einzeln via SSH und "vi" oder "nano" hinzufügen)
PHP-Programme haben viele Schwachstellen, das Übertragen von "bösen" Eingaben ist da nur ein Punkt, den man in allen Sprachen beachten muss.
Sobald Du Strings bekommst, solltest Du davon ausgehen, dass diese Strings bösartig sind. Benutzer sind immer böse. Das bedeutet im Klartext, dass Du sie immer so kodieren solltest, dass sie Dir die Eingaben nichts kaputtmachen:
Ich will hinterher auf dem Server Filemirroring für diverse OpenSource Projekte bereitstellen, da bekommt jeder Benutzter ein Verzeiniss, das eine Grafische oberfläche für die "Public" bereitstellt(und die zu mirrorenden Dateien), und ein Zentrales Adminpanel in der login.php. Da hätte ich fast einen wohlmöglich fatalen Fehler gemacht:
<A href="login.php?dest=deletefile&filename=$Username/$file">Delete</A>

Das wäre schiefgegangen... Jetzt hab ich nurnoch:
<A href="login.php?dest=deletefile&filename=/$file">Delete</A>

Und der Username wird vom Script vor dem löschen dazugestellt, so kann der entsprechende Benutzer nurnoch in seinem Verzeichniss randalieren, aber was passiert jetzt, wenn der:
login.php?dest=deletefile&filename=/../index.php
eingibt? Ich habs probiert, wurde ein Fehler ausgelöst(weil nur das Benutzerverzeichniss den chmod 777 hat). Könnte das aber auch Browsermäßig "knackbar" sein? Z.b. noch weiter zurück? Wieweit haben der apache und php User/group zugriff?

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Sicheres PHP

Beitrag von Xin » Fr Jan 02, 2009 8:54 am

Jside hat geschrieben:Also mySQL will ich sowieso nicht unbedingt benutzten, die Passwörter/Benutzernamen sollen in einer PHP Datei als Array abgespeichert werden(dann aber als MD5)(Muss ich halt jeden Benutzter einzeln via SSH und "vi" oder "nano" hinzufügen)
Dann musst Du sicherstellen, dass die Strings keine Steuerzeichen Deines Fileformates annehmen können. (Nullbyte, Komma, Semikolon, ...?)
Jside hat geschrieben:Da hätte ich fast einen wohlmöglich fatalen Fehler gemacht:
<A href="login.php?dest=deletefile&filename=$Username/$file">Delete</A>

Das wäre schiefgegangen... Jetzt hab ich nurnoch:
<A href="login.php?dest=deletefile&filename=/$file">Delete</A>

Und der Username wird vom Script vor dem löschen dazugestellt, so kann der entsprechende Benutzer nurnoch in seinem Verzeichniss randalieren,
Die vorherige Version wäre schon eine herbe Sicherheitslücke gewesen.
Diese ist allerdings in dem Fall eine Schwäche im Konzept, nicht in PHP. Das macht PHP nicht unsicher, aber PHP lädt auch nicht unbedingt dazu ein, sich gute Konzepte auszudenken...
Jside hat geschrieben:aber was passiert jetzt, wenn der:
login.php?dest=deletefile&filename=/../index.php
eingibt? Ich habs probiert, wurde ein Fehler ausgelöst(weil nur das Benutzerverzeichniss den chmod 777 hat). Könnte das aber auch Browsermäßig "knackbar" sein? Z.b. noch weiter zurück? Wieweit haben der apache und php User/group zugriff?
Hier ist der Punkt, dass Apache überall zugriff drauf haben muss, denn jeder User will ja löschen können.
Du könntest allerdings nach einem chroot Befehl suchen und diesen vor kritischen Operationen ausführen. Somit kann der User nicht mehr höher als Root hinaus gehen und wenn Root sein privates Verzeichnis ist, so kann er mit .. nicht höher gelangen.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Jside
Beiträge: 377
Registriert: Di Nov 11, 2008 12:56 am

Re: Sicheres PHP

Beitrag von Jside » Fr Jan 02, 2009 2:26 pm

Hier ist der Punkt, dass Apache überall zugriff drauf haben muss, denn jeder User will ja löschen können.
Du könntest allerdings nach einem chroot Befehl suchen und diesen vor kritischen Operationen ausführen. Somit kann der User nicht mehr höher als Root hinaus gehen und wenn Root sein privates Verzeichnis ist, so kann er mit .. nicht höher gelangen.
Ok, das hab ich jetzt gelöst, vor dem löschen wird der Dateipfad überprüft, und wenn er außerhalb des Userordners landet, wird eine Fehlermeldung ausgelöst, und mir eine Email mit dem Benutzernamen, der IP unddem Host desjenigen zugesendet. desweiterem hab ich auchmal mit wget -r http://localhost mal probiert, was der alles Downloadet, war nichts dabei, was nicht für die Public freigegeben ist, dann noch eine shoutbox/chat mit AJAX in das User-Mirror-Controll-Panel und ferrdich sieht schon ganz gut aus ;) Jetzt bastle ich gerade an dem Cookiesystem, das da nocheine coockie mit einem MD5 Hash mitgegeben wird, der sich immer um 00:00 Uhr ändert. Somit muss man ab 00:00 Uhr wieder sein Passwort eintippen. Das verhindert, das jemand, größeren schaden anstellt, wenn er kein Benutzer ist, und sich unautorisiert über die Cookies eines Benutzters Zugang verschafft(diese werden zwar gelöscht, aber man weiß ja nie...)

Die Benutzernamen und Passwörter sind ab jetzt MD5 gehasht, und bevor diese geladen werden wird zusätzlich die php Datei mitdiesen ebenfalls via md5_file überprüft. So dürfte das ganze jetzt doch recht sicher sein....


P.s. http://www.golem.de/0901/64352.html *lach* ..wird wohl Zeit, das jeder seine eigenen Elf Header programmiert und in den Kernel miteinkompiliert....

Dominik
Beiträge: 381
Registriert: Mo Jul 07, 2008 9:39 pm

Re: Sicheres PHP

Beitrag von Dominik » Fr Jan 09, 2009 9:01 am

viel zu selten hier:

1. php ist gut Programmiert genau so sicher wie jede Sprache
2. PHP kann man nur "hacken" wenn User was an PHP eingeben können
3. Deswegen gilt: trau nie den eingaben der user
4. jede get/post/cookie wert der unmittelbar in einen query geschaltet wird mit der funktion: mysql_real_escape_string() sichern
5. bei nicht mysql eintragen den typ ermitteln und je nachdem mit intval(), addslashes() sichern
6. aber nicht nur das reicht aus , der user kann auch XSS Angriffe machen, dh bei eingaben auch noch htmlspecialchars() verwenden

7.@xin
so einfach ist es dann doch nicht mit:
username' ); DROP TABLE Users; SELECT * FROM Somewhere WHERE ( id = '1
Könntest du theoretisch zwar schon löschen udn abfragen aber bei einem Normalen Schreibtstiel funktioniert das nicht da:

mysq_query("") <- nur eine zulässt , dh du könntest hier maximal eine subquery machen mit "UNION" , was aber schon schlimm genug ist


mfg
Rechtschreibefehler sind gewollt und dienen der Unterhaltung

Benutzeravatar
Jside
Beiträge: 377
Registriert: Di Nov 11, 2008 12:56 am

Re: Sicheres PHP

Beitrag von Jside » Di Mär 10, 2009 8:22 pm

So ich hab das mal jetzt überarbeitet:

Code: Alles auswählen

<?php
    $Dest = $_GET['dest'];
    session_start();
    if($Dest == "login") {
        if(isset($_POST['username'])) $Username = $_POST['username'];
        if(isset($_POST['password'])) $Password = $_POST['password'];
        if(!Loginprep($Username,md5($Password))) {
            $_SESSION['name'] = $Username;
            $_SESSION['password'] = md5($Password);
        }
    }
    /*Prüfung bei jedem Seitenaufruf*/
    if(!isset($_SESSION['name'])) Logout("Session was destroyed. Please login again!");
    else if(!isset($_SESSION['password'])) Logout("Session was destroyed. Please login again!");
Die Funktion Loginprep gibt 0 Zurück, wenn der User in der Datenbank ist. Die Seite ist Sekundär, auf der Index.php ist die Form zum Anmelden, jetzt dürfte es eigentlich nichtmehr möglich sein, sich ungewollt Zutritt zu verschaffen?!, esseiden man hat sich mit der Form auf der index.php mit uac.php?dest=login angemeldet. Oder hab ich was übersehen? Ist da so einigermaßen sicher?

Mein Server braucht nurnoch SATA HDDs(schon bestellt), und dann gehts los, Port 80 wird von meinem Router auch schon geforwardet fehlt nurnoch DynDNS.
Sollte ich in der Apache2 Conf PHP5 auf php-safe Mod umschalten?

Antworten