Was muss ich bei PHP sicherheitstechnisch beachten?
lima-city → Forum → Programmiersprachen → PHP, MySQL & .htaccess
administrator
beachten
benutzen
code
date
datenbank
datum
eingabe
eintrag
ergebnis
erstellen
fehler
fehlgeschlagen grund
freischaltung
herstellen
http
ordern
reihe
url
verbindung
-
Hi,
ich habe für meine Website jetzt ein Wordpress-Template, eine Gästebuchfunktion und diverse andere kleine Sachen in PHP gemacht und da ich mich eigentlich noch eher zu den PHP-Einsteigern zählen würde, frage ich mich, ob da nicht irgendwo Sicherheitslücken drin sein könnten.
Gibt es irgendwo so eine Art Liste mit "no-go's" beim PHP Programmieren? Was muss ich z.B. beachten, wenn ich Daten vom Nutzer entgegennehme und in der Datenbank ablege (Gästebuch)?
Beitrag zuletzt geändert: 7.8.2011 19:15:11 von roboterbastler -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Die wichtigste Regel, die Du Dir am besten in Dein Hirn einbrennen solltest, ist: Traue KEINEN User-Eingaben, selbst Deinen eigenen nicht!
Alle Werte die nicht direkt aus dem PHP-Skript kommen müssen überprüft werden, ob sie den gewünschten Inhalt enthalten.
Mehr ist eigentlich nicht wirklich zu beachten, ggf. halt noch die üblichen Hinweise ala, Passwörter verschlüsseln, sichere Passwörter für die Datenbank verwenden, MySQL Daten in einer separaten Datei speichern und via .htaccess sichern... und so weiter. Gibt noch ein Haufen mehr Faustregeln die man beachten sollte, Google wird Dir da sicher helfen. -
Zu den DB-Zugriffen solltest du uns am Besten den Code geben, damit wir das genauer betrachten können.
Aber irgendwie kam mir beim Lesen der Gedanke, dass du deinen Code nicht freigeben wolltest und lieber etwas allgemeines dazu hören würdest.
Ich kann dir nur raten, falls dies so ist: Meiner Meinung nach lernt man besser, wenn einem die Fehler / Sicherheitslücken wirklich am eigenen Code gezeigt werden...
Aber etwas Allgemeiner hat strange natürlich recht, nichts ungeprüft durchlassen, wenn es nicht direkt im Code steht.
Zu DB-Aufrufen: Ich denke, ein häufiger Anfänger-Fehler ist es, User-Eingaben / Variablen einfach mit in den String einzuarbeiten.
Ich persönlich verwende PDO (würde ich jedem empfehlen, gerade Einsteigern, damit diese sich gleich daran gewöhnen können und sich nicht auf mysql, etc. festsetzen, ohne Erfahrung damit zu haben), daher kann ich dir keinen Code für mysql, o. ä. liefern.
Daher ein Beispiel einer (ziemlich sicheren) Variablen-Einbindung in PDO:
$userid = $_SESSION['userId']; $sortierungsSpalte = $_GET['sort']; $stmt = 'SELECT * FROM tabelle WHERE User=? ORDER BY ?'; $stmt = $pdo-object->prepare($stmt); $stmt->bindValue(1, $userid); $stmt->bindValue(2, $sortierungsSpalte); $stmt->execute(); while($row = $stmt->fetch()){ tuwas(); }
lg Ole -
Doch, ich kann euch gern mal ein bisschen Code zeigen^^.
Die Gästebuchdaten werden mittels POST vom Formular übertragen und hier erstmal gespeichert:
<?php //MYSQL-Verbindung herstellen $verbindung = mysql_connect('mysql.lima-city.de', 'USER195742', '***********'); if (!$verbindung) { die('MYSQL-Verbindung nicht möglich: ' . mysql_error()); } // benutze Datenbank db_195742_1 $db_selected = mysql_select_db('db_195742_1', $verbindung); if (!$db_selected) { die ('Kann Datenbank nicht benutzen: ' . mysql_error()); } //Evtl neuen Beitrag speichern if(($_POST['name'] != "") && ($_POST['eintrag'] != "")) { $ergebnis = mysql_query("INSERT INTO gaestebuch (`Name`, `Datum`, `Eintrag`, `IP`, `Freigeschaltet`, `EMail`) VALUES ('". $_POST['name'] . "', '" . date('Y-m-d H:i:s') . "', '" . $_POST['eintrag'] . "', '" . $_SERVER["REMOTE_ADDR"] . "', 0, '". $_POST['email'] . "')"); if($ergebnis) { mail('roboterbastler(at)nurfuerspam.de', 'Neuer Gästebucheintrag!', 'Am ' . date('Y-m-d H:i:s') . ' wurde ein neuer Gästebucheintrag geschrieben! Name: ' . $_POST['name'] . ' Eintrag: ' . $_POST['eintrag'], 'From: Webmaster <roboterbastler(at)nurfuerspam.de>'); } else { mail('roboterbastler(at)nurfuerspam.de', 'Fehlgeschlagener Gästebucheintrag', 'Am ' . date('Y-m-d H:i:s') . ' ist ein Gästebucheintrag fehlgeschlagen! Grund: ' . mysql_error(), 'From: Webmaster <roboterbastler(at)nurfuerspam.de>'); } } mysql_close($verbindung); ?>
In der Datenbank warten sie erstmal auf Freischaltung durch mich (eigene Spalte "Freigeschaltet": 0 bzw. 1).
Abgerufen werden die Einträge damit:
<?php //MYSQL-Verbindung herstellen $verbindung = mysql_connect('mysql.lima-city.de', 'USER195742', '************'); if (!$verbindung) { die('MYSQL-Verbindung nicht möglich: ' . mysql_error()); } // benutze Datenbank db_195742_1 $db_selected = mysql_select_db('db_195742_1', $verbindung); if (!$db_selected) { die ('Kann Datenbank nicht benutzen: ' . mysql_error()); } //Bisherige Beiträge anzeigen $ergebnis = mysql_query("SELECT Name, Datum, Eintrag FROM gaestebuch WHERE Freigeschaltet = 1 ORDER BY Datum DESC"); if (!$ergebnis) { die ('Kann SELECT nicht ausführen: ' . mysql_error()); } $reihe = mysql_fetch_row($ergebnis); while($reihe) { echo "<div class=\"GBEintrag\">";//DIV-Container beginnen echo "<p><strong>" . $reihe[0] . "</strong> am <em>" . $reihe[1] . "</em></p>"; echo "<p>" . $reihe[2] . "</p>"; echo "</div>"; $reihe = mysql_fetch_row($ergebnis); } mysql_close($verbindung);?>
Wie prüfe ich denn die Eingaben?
Beitrag zuletzt geändert: 7.8.2011 19:09:39 von roboterbastler -
einiges steht in den links darüber:
http://www.sans.org/top25-software-errors/
http://cwe.mitre.org/top25/
(sonst gleich, aber unterschiedliche diskussionsmaterialien.)
http://phpsecurity.org/code !!
http://sebastian-bergmann.de/archives/501-Professionelle-Softwareentwicklung-mit-PHP-5.html
Beitrag zuletzt geändert: 7.8.2011 23:28:29 von hemiolos -
Danke hemiolos, sieht vielversprechend aus, aber auch nach sehr viel Arbeit!
Ich habe jetzt mal Änderungen vorgenommen. Hier die Gästebuchseite:
<h1>Gästebuch:</h1> <h3>Ich freue mich über Nachrichten!</h3> <p><a href="#NeuerEintrag">Neuen Eintrag erstellen</a></p> <?php global $wpdb; $reihen= $wpdb->get_results("SELECT Name, Datum, Eintrag FROM gaestebuch WHERE Freigeschaltet = 1 ORDER BY Datum DESC", ARRAY_N); foreach($reihen as $eintrag) { echo "<div class=\"GBEintrag\">"; echo "<p><strong>" . $eintrag[0] . "</strong> am <em>" . $eintrag[1] . "</em></p>"; echo "<p>" . $eintrag[2] . "</p>"; echo "</div>"; } ?> <h3>Neuen Eintrag erstellen:<a name="NeuerEintrag"></a></h3> <form method="post" action="<?php echo get_permalink(399); ?>"> <h4>Ihr Name: </h4><input type="text" name="gbname" class="Eingabefeld" /><br/> <h4>E-Mail: </h4><input type="text" name="gbemail" class="Eingabefeld" /><small>Freiwillig und nur für den Administrator (mich) sichtbar</small><br/> <h4>Ihr Eintrag:</h4><textarea name="gbeintrag" cols="80" rows="10" class="Eingabefeld"></textarea><br/> <p><small>Der Eintrag wird erst nach Freischaltung durch den Administrator veröffentlicht!</small></p> <h4>Sicherheitsabfrage:</h4> <?php $img = imagecreatetruecolor(112, 16); imagefill($img, 0, 0, 16185078); imagefttext($img, 14, 0, 1, 13, 0, "./AnkeCalligraph.TTF", "Schraube"); imagepng($img, HOME_LINK . "images/captcha.png"); ?> <img src="<?php echo IMAGES_LINK ; ?>captcha.png" style="margin-left: 4%;" alt="Captcha" /><input type="text" name="gbcaptcha" class="Eingabefeld" /><br/> <p><small>Bitte gib das nebenstehende Wort in das Feld ein.</small></p> <input type="submit" name="gbButton" value="Absenden" class="Button" /> </form>
Hier die verarbeitende Seite:
<h1>Gästebuch</h1> <?php if(((md5($_POST['gbcaptcha']) == '5f17e9655d6ef4981f4bb4ce05308e11') or (md5($_POST['gbcaptcha']) == '6cece31ed5a0d7329183704a3adf4031')) and ($_POST['gbname'] != "") and ($_POST['gbeintrag'] != "")) { echo "<h2>Vielen Dank!</h2><h4>Der Eintrag ist sichtbar, sobald er vom Administrator freigeschaltet wurde!</h4><p>Dieses Vorgehen ist leider zur Vermeidung von Spam nötig.</p> <p><a href=\"" . get_permalink(136) . "\">Zurück zum Gästebuch</a></p>"; global $wpdb; $ergebnis = $wpdb->insert("gaestebuch", array('Name' => $_POST['gbname'], 'Datum' => date('Y-m-d H:i:s'), 'Eintrag' => $_POST['gbeintrag'], 'IP' => $_SERVER["REMOTE_ADDR"], 'Freigeschaltet' => 0, 'EMail' => $_POST['gbemail'])); if($ergebnis) { mail('roboterbastler@nurfuerspam.de', 'Neuer Gästebucheintrag!', 'Am ' . date('Y-m-d H:i:s') . ' wurde ein neuer Gästebucheintrag geschrieben! Name: ' . $_POST['gbname'] . ' Eintrag: ' . $_POST['gbeintrag'], 'From: Webmaster <roboterbastler@nurfuerspam.de>'); } else { mail('roboterbastler@nurfuerspam.de', 'Fehlgeschlagener Gästebucheintrag', 'Am ' . date('Y-m-d H:i:s') . ' ist ein Gästebucheintrag fehlgeschlagen! Grund: ' . mysql_error(), 'From: Webmaster <roboterbastler@nurfuerspam.de>'); } } else { echo "<h2>Entschuldigung!</h2><h4>Es gab einen Fehler!</h4>"; if(($_POST['gbname'] == "") or ($_POST['gbeintrag'] == "")) { echo "<p>Es wurden nicht alle nötigen Felder ausgefüllt!</p>"; } if((md5($_POST['gbcaptcha']) != '5f17e9655d6ef4981f4bb4ce05308e11') and (md5($_POST['gbcaptcha']) != '6cece31ed5a0d7329183704a3adf4031')) { echo "<p>Die Sicherheitsabfrage wurde nicht korrekt beantwortet!</p>"; } echo "<p><a href=\"" . get_permalink(136) . "\">Zurück zum Gästebuch</a></p>"; } ?>
Gibt es noch Verbesserungsvorschläge?
Ich habe das Gästebuch jetzt vorerst so umgestaltet, dass ich z.B. die Datenbankverbindung von Wordpress nutze (und nicht nochmal Zugangsdaten reinschreibe), außerdem habe ich eine Captcha-ähnliche Sicherheitsabfrage eingebaut.
PS: Mir fällt grad auf, das mit md5(), um die Sicherheitsabfrage zu überprüfen, ist eigentlich überflüssig. Könnte ich auch im Klartext reinschreiben oder?
Beitrag zuletzt geändert: 8.8.2011 17:27:31 von roboterbastler -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage