Andreas
09.08.2007, 17:29
Dies kann und soll kein Crashkurs in Sachen "guter" (PHP) Programmierung werden, aber auf einige elementare Dinge die einem das Leben leichter machen möchte ich doch eingehen.
Das A und O ist gut lesbarer Code!
Nichts ist schlimmer als "Spaghetti-Code" bei dem alles in der gleichen Spalte steht.
Am besten ist es, man hält sich an die vBulletin Code Standards, dies ist jedoch nicht zwingend erforderlich.
Hier einige wichtige Punkte der Code standards
Eirückung per Tab
AND und OR sollen verwendet werden, nicht && und ||
Funktions-/Methodennamen kleingeschrieben, ggf. mit unterStrich
Beispiel: print_my_foorow()
Keine Leerzeichen um Argumente/Klammern
Bei if-Abfragen die Blöcke immer in einer neuen Zeile beginnen lassen:
PHP:
----------
Der Inhalt dieses Abschnitts ist nur für Lizenznehmer sichtbar, Sie werden derzeit jedoch nicht als Lizenzinhaber erkannt.<br />
<br />
Bitte öffnen Sie den <a href="http://members.vbulletin-germany.com/membersupport_priority.php">Kundenbereich</a>, tragen Sie Ihre E-Mail-Adresse ein, mit der Sie sich hier registriert haben und aktivieren Sie die Lizenzüberprüfung für http://www.vbulletin-germany.org.
----------
Tabellen/Feldnamen ohne Unterstrich
Mindestens ebensowichtig wie das reine Struktur des Codes ist es sicher und möglichst effizient zu programmieren.
2 Punkte sind hierbei insbesondere bei PHP-Scripten sehr wichtig: Cross Site Scription (XSS) und SQL Injections.
Als Cross Site Scripting bezeichnet man die Möglichkeit, dass ein Angreifer eigenen HTML-Code einschleusen kann, bei einer SQL Injection ist es möglich direkt Datenbankabfragen zu manipulieren.
Hier ein (bewusst extrem schlechtes!) Beispiel-Script um beide Probleme zu demonstrieren.
PHP:
----------
Der Inhalt dieses Abschnitts ist nur für Lizenznehmer sichtbar, Sie werden derzeit jedoch nicht als Lizenzinhaber erkannt.<br />
<br />
Bitte öffnen Sie den <a href="http://members.vbulletin-germany.com/membersupport_priority.php">Kundenbereich</a>, tragen Sie Ihre E-Mail-Adresse ein, mit der Sie sich hier registriert haben und aktivieren Sie die Lizenzüberprüfung für http://www.vbulletin-germany.org.
----------
Eigentlich sieht das Script so aus als würde es das tun was es soll ...
Aber was passiert wenn man als Vorname z.B. <script type="text/javascript">alert('XSS');</script> eingibt?
Dann gibt das Script den Text wieder aus - das JavaScript wird ausgeführt und schon haben wir eine XSS-Lücke.
Noch besser: Eingabe ' OR vorname != '
Dann ergibt sich als Datenbankabfrage
CODE:
----------
Der Inhalt dieses Abschnitts ist nur für Lizenznehmer sichtbar, Sie werden derzeit jedoch nicht als Lizenzinhaber erkannt.<br />
<br />
Bitte öffnen Sie den <a href="http://members.vbulletin-germany.com/membersupport_priority.php">Kundenbereich</a>, tragen Sie Ihre E-Mail-Adresse ein, mit der Sie sich hier registriert haben und aktivieren Sie die Lizenzüberprüfung für http://www.vbulletin-germany.org.
----------
was dann mal gerade alle Datensätze löscht, und nicht nur den gewünschten.
Was kann man nun tun um beides zu verhindern?
Niemals Eingabedaten direkt zur Ausgabe oder für Datenbankabfragen verwenden!
Es sollten immer die Input-Cleaner ($vbulletin->input->clean_array_gpc()) verwendet werden bevor Eingabedaten weiter verrbeitet werden.
Diese Methode stellt sicher dass die Eingabedaten tatsächlich den erwarteten Typ haben.
Beispiel
PHP:
----------
Der Inhalt dieses Abschnitts ist nur für Lizenznehmer sichtbar, Sie werden derzeit jedoch nicht als Lizenzinhaber erkannt.<br />
<br />
Bitte öffnen Sie den <a href="http://members.vbulletin-germany.com/membersupport_priority.php">Kundenbereich</a>, tragen Sie Ihre E-Mail-Adresse ein, mit der Sie sich hier registriert haben und aktivieren Sie die Lizenzüberprüfung für http://www.vbulletin-germany.org.
----------
Durch die Verwendung von TYPE_NOHTML ist hierbei bereits sichergestellt dass diese Variable kein HTML enthält.
Wenn die Möglichkeit besteht dass ein auszugebender Text HTML enthält so muss dieser zuvor mit htmlspecialchars_uni() behandetl werden damit kein XSS möglich ist.
Beispiel
PHP:
----------
Der Inhalt dieses Abschnitts ist nur für Lizenznehmer sichtbar, Sie werden derzeit jedoch nicht als Lizenzinhaber erkannt.<br />
<br />
Bitte öffnen Sie den <a href="http://members.vbulletin-germany.com/membersupport_priority.php">Kundenbereich</a>, tragen Sie Ihre E-Mail-Adresse ein, mit der Sie sich hier registriert haben und aktivieren Sie die Lizenzüberprüfung für http://www.vbulletin-germany.org.
----------
In Datenbankabfragen sollten Strings immer mit $db->escape_string() behandelt werden damit keine SQL Injection möglich ist.
Beispiel
PHP:
----------
Der Inhalt dieses Abschnitts ist nur für Lizenznehmer sichtbar, Sie werden derzeit jedoch nicht als Lizenzinhaber erkannt.<br />
<br />
Bitte öffnen Sie den <a href="http://members.vbulletin-germany.com/membersupport_priority.php">Kundenbereich</a>, tragen Sie Ihre E-Mail-Adresse ein, mit der Sie sich hier registriert haben und aktivieren Sie die Lizenzüberprüfung für http://www.vbulletin-germany.org.
----------
In Templates dürfen niemals $_POST, $_GET, $_REQUEST, $_COOKIE-Variablen direkt verwendet werden.
Noch ein paar Worte zur Effizienz:
Vielfach sieht man Hacks die weit mehr Datenbankabfragen verwenden als nötig.
Meist stehen benötigte Informationen nämlich bereits zur Verfügung, ohne dass man diese neu abfragen müsste.
Für häufig verwendete Datenobjekte gibt es daher fetch_xxx-Funktioen.
Braucht man also z.B. die Info für ein Forum sollte fetch_foruminfo() verwendet werden, für Threads fetch_threadinfo() usw.
Diese Funktionen verwenden Caches, somit ist (im Regelfall) sichergestellt dass keine unnötigen Abfragen ausgeführt werden.
Auch sollte man es vermeiden Abfragen in Schleifen auszuführen.
Sollte es nötig erscheinen dies zu tun, so liegt mit 99,99% Wahrscheinlichkeit ein Fehler in der Codestruktur vor und man ist gut beraten einfach mal nachzufragen wie man das vielleicht besser machen könnte.
Ein Klassiker für Abfragen in Schleifen ist z.B. der Einstiegspunkt postbit_display_[start|complete].
Hier eingepflegte Plugins werden für jeden Beitrag 1x ausgeführt - ein ganz schlechter Platz für Abfragen also.
Das A und O ist gut lesbarer Code!
Nichts ist schlimmer als "Spaghetti-Code" bei dem alles in der gleichen Spalte steht.
Am besten ist es, man hält sich an die vBulletin Code Standards, dies ist jedoch nicht zwingend erforderlich.
Hier einige wichtige Punkte der Code standards
Eirückung per Tab
AND und OR sollen verwendet werden, nicht && und ||
Funktions-/Methodennamen kleingeschrieben, ggf. mit unterStrich
Beispiel: print_my_foorow()
Keine Leerzeichen um Argumente/Klammern
Bei if-Abfragen die Blöcke immer in einer neuen Zeile beginnen lassen:
PHP:
----------
Der Inhalt dieses Abschnitts ist nur für Lizenznehmer sichtbar, Sie werden derzeit jedoch nicht als Lizenzinhaber erkannt.<br />
<br />
Bitte öffnen Sie den <a href="http://members.vbulletin-germany.com/membersupport_priority.php">Kundenbereich</a>, tragen Sie Ihre E-Mail-Adresse ein, mit der Sie sich hier registriert haben und aktivieren Sie die Lizenzüberprüfung für http://www.vbulletin-germany.org.
----------
Tabellen/Feldnamen ohne Unterstrich
Mindestens ebensowichtig wie das reine Struktur des Codes ist es sicher und möglichst effizient zu programmieren.
2 Punkte sind hierbei insbesondere bei PHP-Scripten sehr wichtig: Cross Site Scription (XSS) und SQL Injections.
Als Cross Site Scripting bezeichnet man die Möglichkeit, dass ein Angreifer eigenen HTML-Code einschleusen kann, bei einer SQL Injection ist es möglich direkt Datenbankabfragen zu manipulieren.
Hier ein (bewusst extrem schlechtes!) Beispiel-Script um beide Probleme zu demonstrieren.
PHP:
----------
Der Inhalt dieses Abschnitts ist nur für Lizenznehmer sichtbar, Sie werden derzeit jedoch nicht als Lizenzinhaber erkannt.<br />
<br />
Bitte öffnen Sie den <a href="http://members.vbulletin-germany.com/membersupport_priority.php">Kundenbereich</a>, tragen Sie Ihre E-Mail-Adresse ein, mit der Sie sich hier registriert haben und aktivieren Sie die Lizenzüberprüfung für http://www.vbulletin-germany.org.
----------
Eigentlich sieht das Script so aus als würde es das tun was es soll ...
Aber was passiert wenn man als Vorname z.B. <script type="text/javascript">alert('XSS');</script> eingibt?
Dann gibt das Script den Text wieder aus - das JavaScript wird ausgeführt und schon haben wir eine XSS-Lücke.
Noch besser: Eingabe ' OR vorname != '
Dann ergibt sich als Datenbankabfrage
CODE:
----------
Der Inhalt dieses Abschnitts ist nur für Lizenznehmer sichtbar, Sie werden derzeit jedoch nicht als Lizenzinhaber erkannt.<br />
<br />
Bitte öffnen Sie den <a href="http://members.vbulletin-germany.com/membersupport_priority.php">Kundenbereich</a>, tragen Sie Ihre E-Mail-Adresse ein, mit der Sie sich hier registriert haben und aktivieren Sie die Lizenzüberprüfung für http://www.vbulletin-germany.org.
----------
was dann mal gerade alle Datensätze löscht, und nicht nur den gewünschten.
Was kann man nun tun um beides zu verhindern?
Niemals Eingabedaten direkt zur Ausgabe oder für Datenbankabfragen verwenden!
Es sollten immer die Input-Cleaner ($vbulletin->input->clean_array_gpc()) verwendet werden bevor Eingabedaten weiter verrbeitet werden.
Diese Methode stellt sicher dass die Eingabedaten tatsächlich den erwarteten Typ haben.
Beispiel
PHP:
----------
Der Inhalt dieses Abschnitts ist nur für Lizenznehmer sichtbar, Sie werden derzeit jedoch nicht als Lizenzinhaber erkannt.<br />
<br />
Bitte öffnen Sie den <a href="http://members.vbulletin-germany.com/membersupport_priority.php">Kundenbereich</a>, tragen Sie Ihre E-Mail-Adresse ein, mit der Sie sich hier registriert haben und aktivieren Sie die Lizenzüberprüfung für http://www.vbulletin-germany.org.
----------
Durch die Verwendung von TYPE_NOHTML ist hierbei bereits sichergestellt dass diese Variable kein HTML enthält.
Wenn die Möglichkeit besteht dass ein auszugebender Text HTML enthält so muss dieser zuvor mit htmlspecialchars_uni() behandetl werden damit kein XSS möglich ist.
Beispiel
PHP:
----------
Der Inhalt dieses Abschnitts ist nur für Lizenznehmer sichtbar, Sie werden derzeit jedoch nicht als Lizenzinhaber erkannt.<br />
<br />
Bitte öffnen Sie den <a href="http://members.vbulletin-germany.com/membersupport_priority.php">Kundenbereich</a>, tragen Sie Ihre E-Mail-Adresse ein, mit der Sie sich hier registriert haben und aktivieren Sie die Lizenzüberprüfung für http://www.vbulletin-germany.org.
----------
In Datenbankabfragen sollten Strings immer mit $db->escape_string() behandelt werden damit keine SQL Injection möglich ist.
Beispiel
PHP:
----------
Der Inhalt dieses Abschnitts ist nur für Lizenznehmer sichtbar, Sie werden derzeit jedoch nicht als Lizenzinhaber erkannt.<br />
<br />
Bitte öffnen Sie den <a href="http://members.vbulletin-germany.com/membersupport_priority.php">Kundenbereich</a>, tragen Sie Ihre E-Mail-Adresse ein, mit der Sie sich hier registriert haben und aktivieren Sie die Lizenzüberprüfung für http://www.vbulletin-germany.org.
----------
In Templates dürfen niemals $_POST, $_GET, $_REQUEST, $_COOKIE-Variablen direkt verwendet werden.
Noch ein paar Worte zur Effizienz:
Vielfach sieht man Hacks die weit mehr Datenbankabfragen verwenden als nötig.
Meist stehen benötigte Informationen nämlich bereits zur Verfügung, ohne dass man diese neu abfragen müsste.
Für häufig verwendete Datenobjekte gibt es daher fetch_xxx-Funktioen.
Braucht man also z.B. die Info für ein Forum sollte fetch_foruminfo() verwendet werden, für Threads fetch_threadinfo() usw.
Diese Funktionen verwenden Caches, somit ist (im Regelfall) sichergestellt dass keine unnötigen Abfragen ausgeführt werden.
Auch sollte man es vermeiden Abfragen in Schleifen auszuführen.
Sollte es nötig erscheinen dies zu tun, so liegt mit 99,99% Wahrscheinlichkeit ein Fehler in der Codestruktur vor und man ist gut beraten einfach mal nachzufragen wie man das vielleicht besser machen könnte.
Ein Klassiker für Abfragen in Schleifen ist z.B. der Einstiegspunkt postbit_display_[start|complete].
Hier eingepflegte Plugins werden für jeden Beitrag 1x ausgeführt - ein ganz schlechter Platz für Abfragen also.