Portal > Foren > Ankündigungen, News und Feedback > Tutorials > [PHP] Sichere PHP-Web-Applikationen schreiben
Antwort
 
Themen-Optionen
Alt 28.11.2005, 16:34 Nach oben    #1
Corvin Gröning
 
Benutzerbild von Corvin
 
Registriert seit: 19.03.2005
Ort: S-H | Flensburg
Beiträge: 449
Standard

Sichere PHP-Web-Applikationen schreiben

Inhalt:
Einleitung
1. register_globals
2. XSS
3. CSRF
4. SQL-Injection
5. Versteckte Formularfelder
6. Sessions
7. Variabler Funktionsaufruf
8. Variabler Include
9. Schutz vor ScreenScraping durch CAPTACHs
10. Fremde PHP-Skripte
11. Server-Logs
12. Speichern von Passwörtern
13. Schutz von E-Mail-Adressen
14. Fazit

Geändert von Ben (23.05.2007 um 22:09 Uhr).
Corvin ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2005, 16:34 Nach oben    #2
Corvin Gröning
 
Benutzerbild von Corvin
 
Registriert seit: 19.03.2005
Ort: S-H | Flensburg
Beiträge: 449
Standard

Einleitung
In diesem Tutorial erläutere ich die häufigsten Sicherheitslücken von PHP-Skripten und Möglichkeiten, um diese zu vermeiden.
Ich setze vorraus, dass du mindestens die Grundlagen von PHP, SQL und HTML beherrschst.

Geändert von Corvin (06.04.2008 um 14:24 Uhr).
Corvin ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2005, 16:34 Nach oben    #3
Corvin Gröning
 
Benutzerbild von Corvin
 
Registriert seit: 19.03.2005
Ort: S-H | Flensburg
Beiträge: 449
Standard

1. register_globals
register_globals ist eine Einstellungsmöglichkeit von PHP. Wenn diese aktiviert ist, ist ein direkter Zugriff auf Variablen, die via GET- oder POST-Methode übergeben wurden möglich.

Beispiel:
Code:
<form method="POST" action="getData.php" name="myform">
<input type="text" name="username" width="100" /><br />
<input type="password" name="password" width="100" /><br />
<input type="submit" name="login" />
</form>
Nun kann in der PHP-Datei direkt auf den Usernamen und das Passwort zugegriffen werden:
Code:
$userdata = array();
$userdata['name'] = $username;
$userdata['pass'] = $password;
Wenn register_globals deaktiviert ist, ist kein direkter Zugriff möglich, auf die Daten aus dem Formular kann nur über das superglobale Array $_POST zugegriffen werden:
Code:
$userdata = array();
$userdata['name'] = $_POST['username'];
$userdata['pass'] = $_POST['password'];
Das Gleiche gilt auch für Variablen die mit der GET-Methode (über den URL) übergeben werden, das zugehörige superglobale Array ist $_GET.

Der direkte Zugriff ist zwar etwas kürzer, er stellt aber ein großes Sicherheitsrisiko dar.

Beispiel:
Code:
<?php
echo '<form action="" name="login" method="POST">';
echo '<input type="text" name="username" width="100" />';
echo '<input type="password" name="password" width="100" />';
echo '<input type="submit" value="Login" />';
echo '</form>';

// check username and password
if( $_POST['username'] == "foo" AND $_POST['password'] == "bar" ) {
    $logged_in = true;
}

// check if the user is logged in
if( $logged_in == true ) {
    // print secret data
    echo "Your secret data";
}
?>
Wenn der Benutzer den richtigen Benutzernamen und das richtige Passwort eingibt wird "Your secret data" ausgegeben. Ein Angreifer kann dieses Login bei aktiviertem register_globals ganz einfach umgehen, indem er ?logged_in=true an den URL anhängt. Damit macht er aus diesem Code-Abschnitt:
Code:
// check if the user is logged in
if($logged_in == true) {
    // print secret data
    echo "Your secret data";
}
praktisch diesen:
Code:
$logged_in = true;
// check if the user is logged in
if($logged_in == true) {
    // print secret data
    echo "Your secret data";
}
Aus diesem Grund sollte register_gloabls auf jeden Fall deaktiviert werden.
Alternativ kannst du auch "$logged_in = false;" an den Anfang des Skriptes schreiben (z. B. wenn du bei deinem Hoster kein Zugriff auf die php.ini hast).

Link zu dem Thema:
http://php.net/register_globals

Geändert von Corvin (06.04.2008 um 14:25 Uhr).
Corvin ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2005, 16:34 Nach oben    #4
Corvin Gröning
 
Benutzerbild von Corvin
 
Registriert seit: 19.03.2005
Ort: S-H | Flensburg
Beiträge: 449
Standard

2. XSS
XSS ist die Abkürzung für Cross Site Scripting (es wurde mit XSS abgekürzt, weil CSS schon als Abkürzung für Cascading Style Sheets verwendet wird und im englischen cross häufig mit einem X abgekürzt wird).
XSS ist der Versuch, fremden Code auf einer fremden Webseite zur Ausführung zu bringen.

Als Beispiel folgendes XSS-gefährdetes Gästebuch:
Code:
<?php
/*---------------- 
 * mini guestbook
 *----------------
 */
$gbfile = "gb.txt";

// what to do?
$action = @$_GET['action'];

switch ($action) {
    case "write":
        write();
        break;
    case "edit":
        // ...
        break;
    case "delete":
        // ...
        break;
    default:
        display();
}

// write entries
function write() {
    global $gbfile;

    // print form
    echo '<form action="?action=write" name="gb" method="POST">';
    echo 'Name:<br /> <input type="text" name="author" /><br />';
    echo 'Text:<br /> <textarea name="text" cols="50" rows="5"></textarea><br />';
    echo '<input type="submit" name="submit" value="Write" />';
    echo '</form>';

    // set vars
    $author = $_POST['author'];
    $text = $_POST['text'];

    // write to file if text and author are given
    if (!empty($author) AND !empty($text)) {
        $file = file_get_contents($gbfile);
        $file = $author .": " .$text ."\n{}". $file;
        file_put_contents($gbfile, $file);
    }

    return true;
}

// display entries
function display() {
    global $gbfile;

    echo '<a href="?action=write">New Entry</a><br /><br /><br />';
    
    // print entrys
    $file = file_get_contents($gbfile);
    $file = explode("{}", $file);
    for ( $i=0; $i<count($file)-1; $i++ ) {
        echo stripslashes( $file[$i] ) ."<hr />";
    }
    
    return true;
}
?>
Ein Angreifer könnte nun folgenden als Text eingeben:
Code:
<script>document.location.href="http://domain.tld";</script>
Es wäre dann nicht mehr möglich, die Gästebucheinträge zu lesen, weil von der Seite zum Anzeigen der Einträge immer auf http://domain.tld weitergeleitet werden würde (wenn der Benutzer JavaScript aktiviert hat).

Um sich vor einem solchen Angriff zu schützen, kann man vor der Ausgabe der Einträge (Zeile 60) mit der Funktion htmlentities() alle HTML-Tags in Text umwandeln oder diese mit strip_tags() komplett entfernen.

Beispiel:
Code:
echo htmlentities( stripslashes( $file[$i] ) ) ."<hr />";
oder:
Code:
echo strip_tags( stripslashes( $file[$i] ) ) ."<hr />";
Bei der Verwendung von strip_tags() sollten keine Ausnahmen zugelassen werden ( zweiter Parameter von strip_tags() ). Denn bei
Code:
echo strip_tags( stripslashes( $file[$i] ), "<b>" ) ."<hr />";
wäre es zum Beispiel möglich sowas in das Gästebuch einzutragen:
Code:
<b style="font-size: 1000px; ">Hallo!!</b>
Dadurch würde der Text "Hallo!!" in einer Größe von 1000 Pixeln ausgegeben werden, wodurch das Gästebuch ziemlich verschandelt werden würde.
Um dem Benutzer trotz Vewendung von htmlentities() oder strip_tags() die Möglichkeit zu geben, seinen Text zu formatieren, können entsprechende BBCodes implementiert werden. Ein Tutorial dazu findet sich hier:
[php] BBCode-Parser mit [noparse]-Tag selbst gemacht

Weiterführende Links zum Thema XSS:
http://www.owasp.org/index.php/Cross_Site_Scripting
http://de.wikipedia.org/wiki/XSS

Geändert von Corvin (06.04.2008 um 14:26 Uhr).
Corvin ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2005, 16:35 Nach oben    #5
Corvin Gröning
 
Benutzerbild von Corvin
 
Registriert seit: 19.03.2005
Ort: S-H | Flensburg
Beiträge: 449
Standard

3. CSRF
CSRF steht für Cross Site Request Forgery. Ein CSRF-Angriff ähnelt einem XSS-Angriff, bei ersterem geht es aber primär darum, Objekte (wie Bilder) auf einer fremden Webseite einzubinden.
Als Beispiel das obige Gästebuch, dort ist folgender Eintrag möglich:
Code:
<img src="http://www.bad-site.com/bad-script.php" width="0" height="0" />
Es ist egal, ob das PHP-Skript nun zur Tarnung noch mittels den Bidlfunktionen von PHP ein Bild zurückgibt oder nicht, das Skript wird ausgeführt! Dadurch, dass im <img>-Tag width und height auf 0 gesetzt wurden, wird noch nicht mal das Symbol für eine kaputte Grafik angezeigt, der Angriff wird also vorerst nicht (oder sogar nie) bemerkt.
Ein Angreifer könnte so zum Beispiel die IP-Adressen von Benutzern mitloggen, da das Skript jedes mal ausgeführt wird, wenn jemand sich die Gästebuch-Einträge anschaut.

Das ist noch nicht wirklich bedrohlich, aber ein Angreifer könnte auch folgendes in das Gästebuch eintragen:
Code:
<img src="http://www.domain.tld/buy.php?id=12345&ip=$_SERVER['REMOTE_ADDR']" width="0" height="0" />
Er könnte so also erreichen, das der Benutzer, der sich die Gästebuch-Einträge anschaut, eine Aktion auf einer anderen Webseite tätigt, bei der sogar seine IP-Adresse gespeichert wird, ohne dass der Benutzer davon etwas mitbekommt.

Vor einem CSRF-Angriff schützt man sich genauso, wie vor einem XSS-Angriff. Wenn Bilder per BBCode zugelassen werden, sollte unbedingt überprüft werden, ob es sich bei dem Bild, das eingebunden werden soll, auch wirklich um ein Bild handelt. Zu überprüfen, ob das Bild eine gängige Dateiendung hat (.gif, .jpeg, .png) reicht allerdings nicht aus! Ein Angreifer kann mit einer einfachen Einstellung auf seinem Server festlegen, dass zum Beispiel .gif-Dateien als PHP-Skripte geparst werden sollen (AddHandler application/x-httpd-php .gif in der httpd.conf eines Apache Servers). Das Bild muss also vor dem Anzeigen auf den eigenen Server geladen werden, damit überprüft werden kann, ob es sich tatsächlich um ein Bild handelt. Der URL sollte dann so abgeändert werden, dass er auf das Bild auf dem eigenen Server verweist, so muss es nur einmal, nämlich wenn ein neuer Eintrag abgeschickt wird, auf den Server geladen und überprüft werden.

Eine Demonstration eines CSRF-Angriffs findet sich hier:
http://www.phpfriend.de/forum/ftopic51631.html

Link zum Thema XSS und CSRF:
http://shiflett.org/articles/foiling-cross-site-attacks

Geändert von Corvin (06.04.2008 um 14:26 Uhr).
Corvin ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2005, 16:35 Nach oben    #6
Corvin Gröning
 
Benutzerbild von Corvin
 
Registriert seit: 19.03.2005
Ort: S-H | Flensburg
Beiträge: 449
Standard

4. SQL-Injection
Von SQL-Injection spricht man, wenn ein Angreifer versucht, eine SQL-Abfrage zu manipulieren, um dann SQL-Befehle auszuführen, die nicht vorgesehen waren.

Beispiel:
Bei einem Newssystem gibt es folgende SQL-Query, um News in die Datenbank einzutragen ($title und $text enthalten Daten aus einem Formular
Code:
$sql = "INSERT INTO `news` (`title`, `text`) VALUES ('$title', '$text')";
Ein Angreifer könnte nun folgendes in das Textfeld eingeben:
Code:
'); DELETE FROM news --
Damit sieht die Query nun so aus:
Code:
INSERT INTO `news` (`title`, `text`) VALUES ('$title', ''); DELETE FROM news --')
Es wird so die gesammte Tabelle news gelöscht.

Analyse der Query:
Code:
INSERT INTO news (title, text) VALUES ('$title', ''); 
Damit wird der Titel und ein leerer Text in die Tabelle eingefügt. Mit dem Semikolon am Ende wird die Anweisung abgeschlossen, es kann direkt danach eine neue folgen.

Code:
DELETE FROM news 
Die Tabelle news wird gelöscht.

Code:
--')
Diese Zeichen werden alle ignoriert, denn -- leitet einen SQL-Kommentar ein.

Um sich vor einem SQL-Injection-Angriff zu schützen, muss in der php.ini die Einstellung magic_quotes_gpc auf On gestellt werden. Das bewirkt, dass Sonderzeichen in $_GET, $_POST und $_COOKIE "escaped" werden. Falls bei deinem Hoster magic_quotes_gpc deaktiviert ist und du keinen Zugriff auf die php.ini hast, bietet sich folgende Alternative:
Code:
if ( get_magic_quotes_gpc() == false ) {
   $title = addslashes( $_POST['title'] );
   $text = addslashes( $_POST['text'] );
} else {
    $title = $_POST['title'];
    $text = $_POST['text'];
}
Weiterhin sollte jede SQL-Query, die von einem Benutzer verfasste Daten enthält, auf Plausibilität überprüft und es sollte geprüft werden, ob der Benutzer überhaupt berechtigt ist, die Aktion durchzuführen.

Links zum Thema:
http://php.net/manual/en/security.da...-injection.php
http://www.owasp.org/index.php/SQL_injection
http://www.online-tutorials.net/secu...-t-93-218.html
http://de.wikipedia.org/wiki/SQL-Injektion#PHP

Geändert von Corvin (06.04.2008 um 14:27 Uhr).
Corvin ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2005, 16:35 Nach oben    #7
Corvin Gröning
 
Benutzerbild von Corvin
 
Registriert seit: 19.03.2005
Ort: S-H | Flensburg
Beiträge: 449
Standard

5. Versteckte Formularfelder
Es ist möglich, Werte an ein andere Seite über ein verstecktes Formularfeld zu übergeben, solange der Benutzer nicht in den Quellcode schaut, sieht er nicht, was übergeben wird:
Code:
<!-- weitere Formular-Elemente -->
<input type="hidden" value="wert" />
<!-- weitere Formular-Elemente -->
Als Beispiel wird von einem CMS ausgegangen, in dem die Benutzer die Möglichkeit haben, ihren Account zu löschen. Im Profil der User befindet sich ein Link dazu. Wenn man diesen anklickt, kommt man auf eine Seite, auf der man das Löschen bestätigen muss. Diese Seite sieht so aus:
Code:
<form action="delete_account.php"  name="delete" method="POST">
<input type="hidden" name="id" value="78" />
<input type="submit" value="Ja, meinen Account löschen!" />
</form>
Die Datei delete_account.php hat folgenden Inhalt:
Code:
<?php
// ... Verbindung zur Datenbank

$sql = "DELETE FROM users WHERE id = '".$_POST['id']."'";
mysql_query($sql);
?>
Ein Angreifer könnte sich das Bestätigungsformular auf seinem PC abspeichern und die zweite Zeile wiefolgt verändern:
Code:
<input type="hidden" name="id" value="123" />
Wenn er nun diese Seite (auf seinem PC) aufruft und den Button anklickt wird nicht sein Account sondern der mit der ID 123 gelöscht!
Aus diesem Grund sollten versteckte Formularfelder für solche sensiblen Daten nur verwendet werden, wenn überprüft wird, ob der Benutzer überhaupt berechtigt ist, die dem Inhalt des versteckten Feldes entsprechende Aktion durchzuführen.

Geändert von Corvin (28.08.2008 um 16:35 Uhr).
Corvin ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2005, 16:35 Nach oben    #8
Corvin Gröning
 
Benutzerbild von Corvin
 
Registriert seit: 19.03.2005
Ort: S-H | Flensburg
Beiträge: 449
Standard

6. Sessions
Bei der Verwendung von Sessions sollte folgendes beachtet werden:
Wenn der User die Verwendung von Cookies in seinem Browser aktiviert hat, wird die Session-ID in einem Cookie gespeichert. Wenn er dies nicht hat, wird sie einfach an den URL angehängt, um sie der nächsten Seite zu übergeben. Letzterer Fall stellt ein sehr großes Sicherheitsrisiko dar, denn wenn der Benutzer nun eine Seite geöffnet hat, auf der eine Session gestartet wurde, und nun von dieser aus eine andere Website besucht, wird eventuell der Referer (und damit die Session-ID des Users) mitgeloggt. Über die Session-ID kommen Dritte nun an Daten heran, die eigentlich nicht für sie bestimmt waren. Eine Schutzmaßnahme dagegen wäre, PHP mit aktiviertem session.use_only_cookies zu konfigurieren, dann wird die Session-ID immer in einem Cookie gespeichert. Wenn ein Benutzer die Verwendung von Cookies in seinem Browser deaktiviert hat, schlägt das Starten einer Session fehl!

Weiterhin entsteht ein Sicherheitsrisiko, wenn die Session-ID auf dem Server unverschlüsselt übertragen wird.
Dazu:
SSL

Geändert von Corvin (06.04.2008 um 14:28 Uhr).
Corvin ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2005, 16:36 Nach oben    #9
Corvin Gröning
 
Benutzerbild von Corvin
 
Registriert seit: 19.03.2005
Ort: S-H | Flensburg
Beiträge: 449
Standard

7. Variabler Funktionsaufruf
Gerne verwendet wird ein "variabler Funktionsaufruf". Dabei wird dem PHP-Skript der Name einer Funktion übergeben, welche aufgerufen werden soll. Dies kann hilfreich sein, wenn man z. B. ein Gästebuch innerhalb einer einzigen PHP-Datei geschrieben hat und nun über den URL festgelegt werden soll, ob nun die Einträge angezeigt werden sollen oder ein neuer verfasst werden soll.
Der URL könnte zum Beispiel so aussehen:
guestbook.php?do=display_entries

Und so das Gästebuch:
Code:
function display_entries() {
    // ...
}

function new_entry() {
    // ...
}

$function = $_GET['do'];
$function();
Ein Angreifer kann den URL aber beliebig ändern. Z. B. so:
guestbook.php?do=phpinfo

Damit wird die Funktion phpinfo() aufgerufen und der Angreifer erhält wertvolle Informationen über dein System.

Um sich vor einem solchen Angriff zu schützen sollten die übergebenen Parameter wiefolgt überprüft werden:
Code:
function display_entries() {
    // ...
}

function new_entry() {
    // ...
}

// Prüfen was übergeben wurde
switch( $_GET['do'] ) {
    case "new_entry":
       $function = "new_entry";
       break;
    case "display_entries":
       $function = "display_entries";
       break;
    default:
       $function = "display_entries":
       break;
}

$function();
So ist es nur noch möglich, die Funktionen new_entry() und display_entries() aufzurufen.

Geändert von Corvin (06.04.2008 um 14:28 Uhr).
Corvin ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2005, 16:37 Nach oben    #10
Corvin Gröning
 
Benutzerbild von Corvin
 
Registriert seit: 19.03.2005
Ort: S-H | Flensburg
Beiträge: 449
Standard

8. Variabler Include
Sehr beliebt ist es, für eine Website eine Hauptdatei anzulegen, welche HTML-Kopf und -Fuß (und evt. noch ein paar andere Sachen) enthält und die Seite, die aufgerufen werden soll (zum Beispiel das Impressum oder Gästebuch) in die Mitte der Hauptdatei einzubinden.
Die Links sehen dann etwa so aus:
index.php?action=imprint
index.php?action=guestbook

Und der Code der PHP-Datei so:
Code:
<?php
// HTML-Kopf

include( $_GET['action'].".php" );

// HTML-Fuß
?>
Diese Methode stellt ein sehr großes Sicherheitsrisiko dar: Ein Angreifer kann, indem er den URL-Parameter action verändert, eine beliebige PHP-Datei einbinden und so einen sehr großen Schaden anrichten.
Daher sollten alle Namen der Dateien, die eingebunden werden können, in einem Array gespeichert werden. Über den URL wird dann nicht mehr der Dateinahme, sondern der Schlüssel des Array-Elementes, das den Dateinahmen enthält, übergeben.

Beispiel:
Code:
$files = array( "start" => "start.php",
                        "..." => "..."
                      );
                      
// $_GET['action'] gesetzt?
if ( empty( $_GET['action'] ) ) {
    $key = "start";
} else {
    $key = $_GET['site'];
}

// Existiert die Datei, die eingebunden werden soll?
if ( !@file_exists( $files[$key] ) ) {
    echo "Error!";
} else {
    include( $files[$key] );
}

Geändert von Corvin (06.04.2008 um 14:41 Uhr).
Corvin ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2005, 16:37 Nach oben    #11
Corvin Gröning
 
Benutzerbild von Corvin
 
Registriert seit: 19.03.2005
Ort: S-H | Flensburg
Beiträge: 449
Standard

9. Schutz vor ScreenScraping durch CAPTACHs
Angenommen, auf einer Webseite gibt es ein Umfrage-Skript. Es gibt nun folgende "Angriffsmöglichkeiten":
  1. Jemand der die Umfrage verfälschen will, könnte nun einen Bot schreiben, der, über einen Proxy-Server, auf die Seite mit der Umfrage geht, eine bestimmte Option auswählt und die Umfrage abschickt. Danach wechselt er den Proxy-Server (um die IP-Sperre zu umgehen) und nimmer erneut an der Umfrage teil. Diese Schritte können nun beliebig of wiederholt werden.
  2. Jemand, der die aktuellen Ergebnisse der Umfrage auslesen und auf seiner eigenen Homepage anzeigen lassen will, könnte ein PHP-Skript schreiben, das die Umfrage-Ergebnisse von der fremden Website herausfiltert und ausgibt. Das nennt man "ScreenScraping".

Sogenannte CAPTCHAs (Completely Automated Public Turing-Test to Tell Computers and Humans Apart) sind eine Lösung für das Problem. Sie dienen dazu, einen Menschen von einem Computer zu unterscheiden: Wenn jemand an der Umfrage teilnehmen will oder die Ergebnisse von dieser aufrufen will, wird eine Grafik mit einer verzogenen Zeichenfolge anzeigt (diese Grafiken sind für (die meisten) Bots nicht lesbar), welche der Benutzer in ein Feld eingeben muss.

Links:
http://de.wikipedia.org/wiki/Captcha
http://pear.php.net/package/Text_CAPTCHA

Geändert von Corvin (06.04.2008 um 15:01 Uhr).
Corvin ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2005, 16:37 Nach oben    #12
Corvin Gröning
 
Benutzerbild von Corvin
 
Registriert seit: 19.03.2005
Ort: S-H | Flensburg
Beiträge: 449
Standard

10. Fremde PHP-Skripte
Beim Einsetzen von fremden PHP-Anwendungen (Foren, Gästebücher etc.) auf deinem Server solltest du folgende Punkte beachten:
  • Setze nur PHP-Anwendungen ein, die noch weiterentwickelt werden und dessen Entwickler sich nicht zu viel Zeit beim Veröffentlichen von Bugfixes/Sicherheits-Updates lassen. Solltest du eine PHP-Anwendung verwenden, auf die dies nicht (mehr) zutrifft, solltest du diese unbedingt ersetzen, es sein denn, du sorgst selbst für das rechtzeitige Stopfen von Sicherheitslücken.
  • Neu erschienene Bugfixes/Sicherheits-Updates solltest du so schnell wie möglich installieren.
  • Entferne die Versionsnummer im Copyright der PHP-Anwendung (wenn die Nutzungsbedingungen das zulassen), das erschwert einen Angriff, da manche Sicherheitslücken nur in ganz bestimmten Versionen existieren.

Geändert von Corvin (06.04.2008 um 15:04 Uhr).
Corvin ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2005, 16:37 Nach oben    #13
Corvin Gröning
 
Benutzerbild von Corvin
 
Registriert seit: 19.03.2005
Ort: S-H | Flensburg
Beiträge: 449
Standard

11. Server-Logs
Die Log-Dateien deines Webservers solltest du so oft wie möglich auswerten, so kannst du einen versuchten Angriff schon früh erkennen und dem Angreifer entsprechend den Weg versperren.

Hilfreiche Tools/Programme um Server-Logs auszuwerten, lassen sich über Google schnell finden.

Geändert von Corvin (09.03.2006 um 21:01 Uhr).
Corvin ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2005, 16:37 Nach oben    #14
Corvin Gröning
 
Benutzerbild von Corvin
 
Registriert seit: 19.03.2005
Ort: S-H | Flensburg
Beiträge: 449
Standard

12. Speichern von Passwörtern
Bei einem Login-System zum Beispiel müssen die Passwörter der Benutzer in einer Datei/Datenbank gespeichert werden. Um die Passwörter zu schützen (falls ein Angreifer sich Zugriff auf den Speicherort der Passwörter verschafft), sollten sie nicht im Klartext, sondern als Hash abgespeichert werden, z. B. als md5-Hash.
http://de.wikipedia.org/wiki/Hash-Funktion
http://de.wikipedia.org/wiki/Md5

Beispiel:
Die Query, um den Benutzernamen und das Passwort bei der Registration in der Datenbank zu speichern, könnte wie folgt lauten (um den md5-Hash des Passworts zu erhalten wird die PHP-Funktion md5 verwendet
Code:
$user = $_GET['user'];
$pw = md5($_GET['pw']);

$sql = "INSERT INTO `users` (`username`, `password`) VALUES ('$user', '$pw')";
Wenn sich nun ein Benutzer einloggen will, wird der md5-Hash des eingegebenen Passwortes erstellt und mit dem aus der Datenbank verglichen:
Code:
$user = $_GET['user'];
$pw = md5($_GET['pw']);

$sql = "SELECT `username` FROM `users` WHERE `username` = '$user' AND `password` = '$pw'";
Einen kleiner Nachteil: Wenn ein Benutzer sein Passwort vergessen hat, ist es nicht mehr möglich, ihm sein Passwort (im Klartext) zuzusenden. Stattdessen muss ihm ein neues zugeschickt werden.

Geändert von Corvin (06.04.2008 um 15:17 Uhr).
Corvin ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2005, 16:38 Nach oben    #15
Corvin Gröning
 
Benutzerbild von Corvin
 
Registriert seit: 19.03.2005
Ort: S-H | Flensburg
Beiträge: 449
Standard

13. Schutz von E-Mail-Adressen
Versender von Spammails lassen oft Bots durch das Internet laufen, die wahllos auf Webseiten nach E-Mail-Adressen suchen, um an diese Spamnachrichten verschicken zu können.

Um sich davor zu schützen, können E-Mail-Adressen z. B. etwas "verschlüsselt" ausgegeben werden: email [ at ] host [ dot ] com anstelle von email@host.com, allerdings durchschauen die meisten Bots das.
Eine sicherere Methode, E-Mail-Adressen zu schützen, ist es, sie als Bild darzustellen.

Weder die "verschlüsselte" E-Mail-Adresse noch das Bild sollten allerdings verlinkt werden (<a href="mailto:email@host.com"> ... </a>), denn Bots, die nach E-Mail-Adressen suchen, analysieren nicht die Ausgabe des Browsers, sondern den Quellcode der HTML-Datei.

Hierfür gibt es allerdings eine sichere Alternative, es kann mittels PHP ein Header an den Browser gesendet werden:
Code:
header("Location:mailto:".$mail);

Geändert von Corvin (06.04.2008 um 15:30 Uhr).
Corvin ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2005, 16:38 Nach oben    #16
Corvin Gröning
 
Benutzerbild von Corvin
 
Registriert seit: 19.03.2005
Ort: S-H | Flensburg
Beiträge: 449
Standard

14. Fazit
Ich hoffe, ich konnte dir hiermit einen guten Einstieg in einige Aspekte der Sicherheit von PHP-Skripten vermitteln.
Wie bereits am Anfang des Tutorials erwähnt, es wurden hier nur einige der häufigsten Sicherheitslücken angesprochen. Du solltest dich auf jeden Fall weiter mit dem Thema befassen. Hier findest du einige Links zu Webseiten, auf denen du weiterarbeiten kannst:
Security-Links

Bei Fragen oder Problemen sind wir dir hier im Forum sehr gerne behilflich.

Geändert von Corvin (06.04.2008 um 15:33 Uhr).
Corvin ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 01.12.2005, 07:37 Nach oben    #17
Goldman.de
 
Benutzerbild von J33d3X
 
Registriert seit: 09.10.2005
Ort: Frankfurt am Main
Beiträge: 190
Standard

kleine Hilfe zu CSRF

PHP-Code:
<?php

        $treffer
=false;
        
$search "/(\[img\])(.*)(\.php)*(\[\/img\])/siU";
        
        
// check auf CrossSiteRequestForgeries
        
preg_match($search$para$treffer);
        if (
true==$treffer && is_array($treffer))
        {
            if (
'.php'==$treffer[3])
            {
                
$replace="replaced by system: do not use pictures with ending  ".$treffer[3];
                
$para=str_replace($treffer[0], $replace$para);
            }
        }
J33d3X ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 02.12.2005, 20:22 Nach oben    #18
Jay
Gast
 
Beiträge: n/a
Standard

Zitat:
Zitat von Corvin Gröning
Aus diesem Grund sollten versteckte Formularfelder nicht verwendetet werden, um solche sensiblen Daten zu übergeben, am besten fährt man, wenn sie garnicht verwendet werden (die bessere Alternative dazu ist das Verwenden von Sessions).
Da bin ich aber anderer Meinung. Bei einem guten CMS wird zuerst überprüft ob der User überhaupt berechtigt ist, einen anderen bzw. genau diesen User zu löschen! Versteckte Formularfelder sind nichts schlechtet und sollten IMHO auch weiterhin verwendet werden.

In Sessions speichere ich Daten die über einen längeren zeitraum benötigt werden.
Zitat:
Zitat von Corvin Gröning
Das ist ja noch nicht wirklich bedrohlich, aber stell dir mal vor, der Angreifer schreibt folgendes in das Gästebuch:
<img src="http://www.shop.tld/buy.php?id=345&ip=$_SERVER['REMOTE_ADDR']" width="0" height="0" />
Das ist auch nicht bedrohlich, weil es bei keinem Online shop reicht einfach auf den Kaufbutton zu klicken (da muss man sich anmelden und und und). Außerdem kann man wohl bei keinem OS einfach PHP befehle ausführen.

Zitat:
Zitat von Corvin Gröning
Niemand kann dich beschuldigen, die Passwörter deiner User gestohlen zu haben, weil du ja nirgendwo die Passwörter im Klartext speicherst, sondern nur die md5-Hashs.
Das ist wohl Blödsinn. Wenn ich der Anbieter bin, brauche ich kein Passwort um mir Zugang zum Account eines users zu machen. Schließlich kann ich einfach auf die db zugreifen und alle relevanten (lesbaren daten) abfragen. Allerdings wäre das max. die Adresse oder eMail, weil Kreditkartennummern wird dir keiner geben, außer du bist ein seriöser Anbieter und dann wiederum willst du, dass dir deine Kunden vertrauen. Weil du ja was verkaufen willst und nicht die KN vom Kunden stehlen.

-- Fat Tony
 
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 02.12.2005, 21:24 Nach oben    #19
Michel
Gast
 
Beiträge: n/a
Standard

zu Punkt 8 hätte ich auch noch eine sichere alternative.
Man speichert die zu includierenden Seiten einfach in einen Unterordner, beispielsweise /inc

PHP-Code:
<?php 
  
if (isset($_GET["seite"])){
    if(@include 
"inc/".$_GET["seite"].".php"){
    }
    else{
      @include 
"inc/start.php";
    }
  }
  else{
    @include 
"inc/start.php";
  }
?>
 
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 02.12.2005, 22:27 Nach oben    #20
Jann Hendrik Bekaan
 
Benutzerbild von Jann Hendrik
 
Registriert seit: 02.12.2004
Ort: Wildeshausen
Beiträge: 2.213
Standard

Zitat:
Zitat von Michel
zu Punkt 8 hätte ich auch noch eine sichere alternative.
und was, wenn die GET-Variable mit ../ beginnt?
Jann Hendrik ist gerade online  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Antwort