Sicherheit (PHP, MySQL Inserts & Selects)

versuch13

Erfahrenes Mitglied
So ich beschäftige mich jetzt schon etwas länger mit PHP & MySQL und so langsam kommt es dann auch die ersten Male zum online Einsatz. Daher möchte ich hier jetzt mal das Thema Sicherheit von MySQL Inserts und Selects aufgreifen. Dazu habe ich schon einiges gelesen, habe natürlich auch mal hier in den Sicherheits Thread geschaut (aber da ist mir einiges einfach noch zu hoch), und jetzt wüßte ich gerne einfach mal wie es um die Sicherheit meiner Scripts steht.

Im groben sieht es bei mir immer ca. so aus:

config.php

PHP:
    define('MYSQL_HOST', '***');
    define('MYSQL_USER', '***');
    define('MYSQL_PASS', '***');
    define('MYSQL_DATABASE', '***');
    
    
    @mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASS) OR
        die("Keine Verbindung zur Datenbank. Fehlermeldung:".mysql_error());
    @mysql_select_db(MYSQL_DATABASE) OR
        die("Konnte Datenbank nicht benutzen, Fehlermeldung: ".mysql_error());        
        
    include "functions.php";


functions.php

PHP:
    # Funktion für die Eingabe, im Insert noch mysql_real_escape_string
    function array_stripslashes($var)
    {
        if(is_string($var)) {
            $var = stripslashes($var);
        } else {
            if(is_array($var)) {
                foreach($var AS $key => $value) {
                    array_stripslashes($var[$key]);
                }
            }
        }
    }
    
    if(get_magic_quotes_gpc()) 
    {
        array_stripslashes($_GET);
        array_stripslashes($_POST);
        array_stripslashes($_COOKIE);
    }
    
    
    # Funktion für die normale Ausgabe
    function fct_text($str) 
    {
        # Allgemeine umformatierungen
        $str = trim($str);
        $str = htmlentities($str, ENT_QUOTES);
        $str = stripslashes($str);       
        $str = nl2br($str);    
        # BBCODE
        $str = preg_replace('=\[url\](.*)\[/url\]=Uis', '<a href="\1">\1</a>', $str);
        $str = preg_replace('#\[url=(.*)\](.*)\[/url\]#Uis', '<a href="\1">\2</a>', $str);    
        return $str;
    }    
    
    
    
    # Funktion die bei MySQL UPDATES zur vorherigen Ausgabe genutzt wird
    function fct_text($str) 
    {
        $str = trim($str);
        $str = stripslashes($str);       
        $str = nl2br($str);    
        return $str;
    }


index.php (mit Beispiel für INSERT und SELECT)

PHP:
<?php

    error_reporting(E_ALL);
    include "inc/config.php";

?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Security Tests</title>
</head>

<body>

<form method="post" action="index.php?send">
    <textarea name="msg"></textarea>
    <input type="submit" name="send">
</form>

<?php

    if(isset($_GET['send'])) 
    {
        $query =     "INSERT INTO table
                        (text)
                    VALUES
                        ('". mysql_real_escape_string($_POST['msg'])."')";                        
        mysql_query($query) OR die(mysql_error());
        echo "Daten wurden hinzugefügt";
    } else {
        $sql =         "SELECT
                         text
                    FROM
                        table
                    ORDER BY
                        id ASC";
        $result = mysql_query($sql) OR die(mysql_error());
        while($row = mysql_fetch_assoc($result)) {
            echo fct_text($row['text'])."<br>\n";
        }        
    }

?>

</body>
</html>


So, dazu jetzt erstmal eine Frage. In meiner index.php inkludiere ich immer zu Anfang die config.php, in welcher ja mysql_connect und mysql_select_db mit drin ist. Kann das so irgendwelchen Nachteile haben?
Sonst interessiert mich einfach ob das so in Ordnung ist, noch weiter ausgebaut werden muss, vielleicht total schwachsinnig ist oder sonstiges?


Vielen Dank. Gruß
 
Hallo,

erstmal muss ich sagen, das der code schon recht vernünftig aussieht, ich habe die funktionalität nur grob überflogen und sage dazu mal folgendes:

mysql functionen in der config sind kein problem, das wird nur serverseitig ausgeführt und ist daher nicht manipulierbar.

Das einzige worauf zu achten ist, sind daten die browser und server austauschen.

eine schwachstelle ist det GET variable send, da du das formular per POST absendest, setze dir ein hidden field ins formular um das zu setzen

<input type="hidden" name="send" value="true">

Dann schaust du ob $_POST['send'] == true

POST daten sind wesentlich schwerer zu manipulieren als GET daten, da ich dafür nur die daten der adressleiste ändern muss.

Also, wenn möglich nicht mit parametern in der URL arbeiten wenn dieses darüber entscheiden soll, ob teile des scriptes ausgeführt werden sollen.

Alle Daten werden mit mysql_real_escape_string übergeben, das stellt sicher das in den übergebenen Daten keine anweisungen enthalten sein können die auf dem system aufgeführt werden können, das ist also gut so.

Gruß
Marcus
 
Die Uebegabe von send per URL kannst Du Dir meiner Meinung nach sparen, auch brauchst Du nicht das von ripkens erwaehnte Hidden-Feld. Dein Submit-Button heisst doch schon send, dementsprechend sollte auch jetzt bereits $_POST['send'] verfuegbar sein.
Bei kurzem Ueberfliegen scheint mir der Code ganz gut zu sein. Genaueres kann man dann sicher mit ein paar Tests herausfinden. Funktioniert das Quoting vernuenftig wenn die Magic-Quotes an sind? Wenn sie aus sind? Koennen vielleicht Variablen manipuliert werden wenn register_globals=on ist?
In meinem letzten Beitrag in Thread Sicherheit in PHP hab ich kurz geschildert wie ich beim Entwickeln von PHP-Scripts vorgehe. Nicht allzu detailiert, aber doch grob den Ablauf aufgezeigt. Vielleicht ist das fuer Dich von Interesse.
 
Dennis Wronka hat gesagt.:
Dein Submit-Button heisst doch schon send, dementsprechend sollte auch jetzt bereits $_POST['send'] verfuegbar sein.
Klar, darauf hätte ich eigentlich kommen müssen. Das über ein weiteres hidden Field zu lösen

Dennis Wronka hat gesagt.:
Bei kurzem Ueberfliegen scheint mir der Code ganz gut zu sein. Genaueres kann man dann sicher mit ein paar Tests herausfinden. Funktioniert das Quoting vernuenftig wenn die Magic-Quotes an sind? Wenn sie aus sind? Koennen vielleicht Variablen manipuliert werden wenn register_globals=on ist?
In meinem letzten Beitrag in Thread Sicherheit in PHP hab ich kurz geschildert wie ich beim Entwickeln von PHP-Scripts vorgehe. Nicht allzu detailiert, aber doch grob den Ablauf aufgezeigt. Vielleicht ist das fuer Dich von Interesse.

Ja also wenn MagicQoutes on ist, denke ich wird richtig escaped:

"Test" -> \"Test\"
\"Test\" -> \\\"TEST\\\"
\ -> \\

Mit MagicQuots off habe ich bisher noch nicht getestet. Aber das müßte ja stimmen oder?

Deinen neuesten Post im Sicherheits Thread hab ich schon gelesen. Beim Seitenaufbau handhabe ich dass immer über ein Array:

PHP:
    $dateien = array(); 
    $dateien['home'] = "home.php";
    $dateien['links'] = "links.php";  
    
    if(isset($_GET['section']) AND isset($dateien[$_GET['section']])) {
        include $dateien[$_GET['section']];
    } else {
        include $dateien['home'];
    }

mit der Überprüfung ob $_GET['section'] im Array $dateien enthalten ist sichere ich mich doch ausreichend gegen das einbinden eines externen Scripts ab oder?


Vielen Dank. Gruß
 
versuch13 hat gesagt.:
Klar, darauf hätte ich eigentlich kommen müssen. Das über ein weiteres hidden Field zu lösen
Wie gesagt, Du braucht kein Hidden-Feld erstellen, Dein Submit-Button heisst doch bereits send.
Das mit dem Datei-Array duerfte in Ordnung gehen.
 
Dennis Wronka hat gesagt.:
Wie gesagt, Du braucht kein Hidden-Feld erstellen, Dein Submit-Button heisst doch bereits send.
Das mit dem Datei-Array duerfte in Ordnung gehen.


Sorry, da ist in dem Post was durcheinander gekommen bzw. weggekommen. Sollte heißen, "dass über ein hidden Feld zu lösen wäre ja unsinnig da wie du bereits erwähnt hast direkt auf $_POST['send'] zugegriffen werden kann."

Ok, vielen Dank nochmal.
 
Hallo!

Also meine persönlich Meinung ist ja dass niemanden z.b. der Datenbankbenutzer etwas angeht.
Genauso wenig wie ob der Server über Localhsot läuft oder über irgendwo.de.

Ich würde dem User nur ein plumpes.....
Code:
Es ist ein Fehler aufgetreten.
Bitte versuchen Sie es zu einem späteren Zeitpunkt nochmal.
Der Webmaster wurde bereits benachrichtig.
aufs Auge drücken.

Das was mysql_error() ausspuckt, würde ich den User erst garnicht zu Gesicht bekommen lassen..... sondern es lieber in eine Logdatei schreiben lassen oder z.b. per eMail-Benachrichtigung zuschicken lassen.

Gruss Dr Dau
 
Die automatischen Fehlermeldungen sind auch nicht für die Öffentlichkeit gedacht. Denn einerseits enthalten sie brisante Informationen und andererseits kann der Benutzer damit auch nichts anfangen, um die Ursache des Fehlers zu ermitteln und zu beheben.
Deshalb würde ich bei Systemfehlern auch nur eine allgemeine Fehlermeldung ausgeben. Fehler, die aufgrund von falschen Benutzereingaben auftraten, sollten jedoch erläutert werden.
 
Zurück